• 面试题_寻找丑数


    最近一直在准备面试,因为要实习了,然后我就纠结了,不知道自己到底处在一个什么样的水平,到底应该选择怎样的实习单位。但是,不管怎么样,还是多看看题吧,感觉面试题还是挺好玩的。最近又在看《编程之美》,感觉有些收获,其实编程真的可以很美,呵呵。

    题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第1500个丑数。

          看过《编程之美》的人,应该都知道书上的解题思路,它总是先从最容易想到的解决方法入手,然后再一直追问,有没有更好的解决方法。我觉得这个解决问题的思路非常好,任何问题都要一遍一遍的推敲,找到最佳的解决方案,从空间和时间上进行双重的优化。

        这道题最简单的思路,就是穷举,穷举所有满足条件的数字。其实,仔细想想,穷举有时可以看成是万能的方法,但是效率也是最低的。

    bool IsUgly(int number)
    {
        while(number % 2 == 0)
            number /= 2;
        while(number % 3 == 0)
            number /= 3;
        while(number % 5 == 0)
            number /= 5;
        return (number == 1) ? true : false;
    }
    
    int Method1(int index)
    {
        if(index <= 0)
            return 0;
     
        int number = 0;
        int uglyFound = 0;
        while(uglyFound < index)
        {
            ++number;
     
            if(IsUgly(number))
            {
                ++uglyFound;
            }
        }
     
        return number;
    }

           上面的方法,效率低的无法让人接受。于是,我们在寻求更好的解决办法。仔细阅读题目,会发现这题貌似有点像找素数的问题,对了,就是这样,我们换个思路,不是去枚举所有符合条件的数,而是去通过条件生成这些数字。根据丑数的定义,丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数。里面的每一个丑数是前面的丑数乘以2、3或者5得到的。这个思路的关键点,就是要保证数组里面的丑数是排好序的。假设arr[1..i]是已经排好序的数组,则arr[i]一定是这里面最大的数,那么我们只要去寻找新生成的数字中比arr[i]大的的最小的数。新生成的数是由前面的数字*2或*3或*5得到的。我们定义index2为前面数字*2中的所有数字中满足大于arr[i]的最小的数的下标,index3,index5类似定义,则应该放在arr[i+1]位置的数字便是min(arr[index2]*2,arr[index3]*3,arr[index5]*5)。

    注意代码里,index2,index3,index5是维持动态向前的,不会产生无效搜索,因为当前找的数字一定比原来找的要大,所以从上一次找到的下标开始进行搜索就可以了。

    具体代码实现如下:

    int Min(int a, int b , int c)
    {
    	a=a<b?a:b;
    	if(c<a) return c;
    	else return a;
    }
    
    int Method2(int Mindex)
    {
    	int index=1;
    	int *arr= new int[Mindex];
    	arr[0]=1;
    	int index2=0, index3=0, index5=0;
    	while(index<Mindex)
    	{
    		int min=Min(arr[index2]*2,arr[index3]*3,arr[index5]*5);
    		arr[index]=min;
    		while(arr[index2]*2<=arr[index]) index2++;
    		while(arr[index3]*3<=arr[index]) index3++;
    		while(arr[index5]*5<=arr[index]) index5++;
    		index++;
    	}
       int ans=arr[Mindex-1];
       delete arr;
    	return ans;
    }
  • 相关阅读:
    2014年10月10号——数据类型之间的转换
    2014年10月9日——语言基础2
    2014年10月9日——语言基础1
    2014年10月8日——进制转换
    js
    SQL的数据类型
    SQL,学习基础2
    SQL数据库的备份和恢复
    用java调用oracle存储过程总结(转)
    用JAVA调用Mysql数据库,数据存储过程的封装与调用;
  • 原文地址:https://www.cnblogs.com/coser/p/1976525.html
Copyright © 2020-2023  润新知