码迷,mamicode.com
首页 > 其他好文 > 详细

剑指offer (34) 丑数

时间:2014-06-26 18:59:43      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:style   class   blog   code   color   strong   

题目:只包含因子2,3,5的数成为 丑数

求从小到大第1500个丑数

通常我们把1当作第一个丑数

 

方法一:逐个判断每个整数是不是丑数

如何判断一个数是不是丑数? 根据定义,丑数只能被2,3,5整除,也就是说,这个数的因子中只能是2,3,5

我们不断用这个数除以2,3,5,直到最后,如果得到1,那么这个数就是丑数

bool IsUgly(int num)
{
    assert(num >= 0);
    while (num % 2 == 0) {
        num /= 2;
    }
    
    while (num % 3 == 0) {
        num /= 3;
    }
    
    while (num % 5 == 0) {
        num /= 5;
    }
    
    return (num == 1) ? true : false;
}

 

接下来,只需要按照顺序来判断每一个整数是不是丑数

 

方法二:

前面一种方法效率低,因为它需要对每个数都进行判断是不是丑数,对于非丑数,花费了许多时间

根据丑数的定义:丑数的因子只能有2,3,5,可以得知 较大丑数除以较小丑数的结果只能是2,3,5的乘积,即相除结果也是丑数

 

我们可以创建一个数组,里面的数字是排好序的丑数。里面的每一个丑数是前面的丑数乘以23或者5得到的

这种思路的关键在于怎样确保数组里面的丑数是排好序的

给定前k个丑数(U1,U2,U3,…,Uk),计算第k+1个丑数Uk+1

第k+1个丑数肯定是前面k个丑数中的某个数乘以2,3,5的一个结果,

在前k个丑数中,分别找到最小的丑数p2,p3,p5使得p2*2>Uk;p3*3>Uk;p5*5>Uk,之后Uk+1=min(p2*2, p3*3, p5*5)

注意:因为当前丑数均排好序,所以下一次寻找p2,p3,p5并不需要从头开始,只需要从上一次的p2,p3,p5开始即可

long long KthUgly(int kth) 
{
    assert(kth >= 1);
    std::vector<long long> ugly(kth, 0);
    int index2 = 0;
    int index3 = 0;
    int index5 = 0;
    
    ugly.at(0) = 1;
    int lastIndex = 0;
    while (lastIndex + 1 != kth) {
        while (ugly.at(index2) * 2 <= ugly.at(lastIndex)) {
            ++index2;
        }
        
        while (ugly.at(index3) * 3 <= ugly.at(lastIndex)) {
            ++index3;
        }
        
        while (ugly.at(index5) * 5 <= ugly.at(lastIndex)) {
            ++index5;
        }
        
        long long min = std::min(std::min(ugly.at(index2) * 2, ugly.at(index3) * 3), ugly.at(index5) * 5);
        ++lastIndex;
        ugly.at(lastIndex) = min;
    }
    return ugly.at(lastIndex);
}

 

 

剑指offer (34) 丑数,布布扣,bubuko.com

剑指offer (34) 丑数

标签:style   class   blog   code   color   strong   

原文地址:http://www.cnblogs.com/wwwjieo0/p/3808455.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!