寻找丑数-算法-java语言

题目:我们把只包含因子

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

分析:这是一道在网络上广为流传的面试题,据说google曾经采用过这道题。

所谓一个数m是另一个数n的因子,是指n能被m整除,也就是n % m == 0。根据丑数的定义,丑数只能被235整除。也就是说如果一个数如果它能被2整除,我们把它连续除以2;如果能被3整除,就连续除以3;如果能被5整除,就除以连续5。如果最后我们得到的是1,那么这个数就是丑数,否则不是。

基于前面的分析,我们可以写出如下的函数来判断一个数是不是丑数:

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 GetUglyNumber_Solution1(int index)

{

    if(index <= 0)

        return 0;

 

    int number = 0;

    int uglyFound = 0;

    while(uglyFound < index)

    {

        ++number;

 

        if(IsUgly(number))

        {

            ++uglyFound;

        }

    }

 

    return number;

}

第二种方法:

分析:假设数组ugly[N]中存放不断产生的丑数,初始只有一个丑数ugly[0]=1,由此出发,下一个丑数由因子2,3,5竞争产生,得到ugly[0]*2, ugly[0]*3, ugly[0]*5, 显然最小的那个数是新的丑数,所以第2个丑数为ugly[1]=2,开始新一轮的竞争,由于上一轮竞争中,因子2获胜,这时因子2应该乘以ugly[1]才显得公平,得到ugly[1]*2,ugly[0]*3,ugly[0]*5, 因子3获胜,ugly[2]=3,同理,下次竞争时因子3应该乘以ugly[1],即:ugly[1]*2, ugly[1]*3, ugly[0]*5, 因子5获胜,得到ugly[3]=5,重复这个过程,直到第n个丑数产生。总之:每次竞争中有一个(也可能是两个)因子胜出,下一次竞争中 胜出的因子就应该加大惩罚!


public class UglyNumber {



public static void main(String[] args) {
System.out.println(isUglyNumber(14));
System.out.println("第1500个丑数是:"+findUgly2(1500));
System.out.println("第1500个丑数是:"+findUgly1(1500));

}
public static boolean isUglyNumber(int number){

while(number%2==0)
number=number/2;
while(number%3==0)
number=number/3;
while(number%5==0)
number=number/5;
return (number==1)?true : false;
}
public static int findUgly1(int index){
if(index<=0)
return 0;

int num=0;
int find=0;
while(find<index){
++num;
if(isUglyNumber(num)){
++find;
}
}
return num;
}


public static int min(int a,int b ,int c){
int temp = a<b? a:b;
return temp<c? temp:c;
}
public static int findUgly2(int n){
int [] ugly = new int[n];   
ugly[0] = 1;   
   int index2 = 0;   
int index3 = 0;   
   int index5 = 0;   
int index = 1;   
   while (index < n)
   {   
       int val = min(ugly[index2]*2, ugly[index3]*3, ugly[index5]*5); //竞争产生下一个丑数   
       if (val == ugly[index2]*2) //将产生这个丑数的index*向后挪一位;  
           ++index2;   
       if (val == ugly[index3]*3)   //这里不能用elseif,因为可能有两个最小值,这时都要挪动;
           ++index3;   
       if (val == ugly[index5]*5)   
           ++index5;   
       ugly[index++] = val;   
   }   
int result = ugly[n-1];   
    
   return result;     
}


}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值