Ugly Numbers(丑数)Dynamic Programming(动态规划

丑数是指只包含质因子2、3和5的数,如1, 2, 3, 4, 5等。求第n个丑数可以采用暴力求解或动态规划方法。动态规划思路是将序列分为3组,每组对应质因子2、3、5的倍数,然后通过类似归并排序的方式合并三个序列,每次选取最小的数并向前推进,直至找到第n个丑数。" 109559118,10139858,历史上著名的电脑病毒大盘点,"['电脑病毒', '网络安全', '程序设计', '历史回顾']
摘要由CSDN通过智能技术生成

所谓的丑数是指只包含质因子2、3和5的数。例如前10个丑数分别为 1, 2, 3, 4, 5, 6, 8, 9, 10, 12. 然后要求求得第n个丑数。

解决此问题主要有两个问题:暴力求解,即挨个找丑数,直到找到第n个,另一种方法就是使用动态规划。

1.简单方法
要检查数字是否为丑数,将该数字除以2、3和5的最大可除幂。如果数字变为1,则它是丑陋的数字,否则不是。例如,让我们看看如何检查300是否为丑数。 2的最大可除幂是4,将300除以4后得到75。3的最大可除幂是3,将75除以3后得到25。5的最大可除幂是25,将25除以25后得到1 由于最后得到1,所以300是丑数。代码如下

class Solution{
//将a除b的最大整数倍
 public int maxDivide(int a, int b)
    {
        while (a % b == 0)
        {
            a = a / b;
        }
        return a;
    }
   //判断 number是否为丑数
    public int isUgly(int number)
    {
        number = maxDivide(number,2);
        number = maxDivide(number,3);
        number = maxDivide(number,5);
        return (number == 1)? 1 : 0;
    }
    //得到第n个丑数
    public int getUglyNo(int n)
    {
        int i = 1;
        int count = 1;
        while (n > count)
        {
            i++;
            if(isUgly(i) == 1)
            {
                count++;
            }       
        }
         return i;
    }
 }
  1. 动态规划
    因为每个数字只能除以2、3、5,所以一种查看序的方法是将序列分成三组,如下所示:
    (1)1×2、2×2、3×2、4×2、5×2,…
    (2)1×3、2×3、3×3、4×3、5×3,…
    (3)1×5、2×5、3×5、4×5、5×5,…

    我们可以发现每个子序列都是丑数序列本身(1、2、3、4、5,…)乘以2、3、5。然后我们使用类似的归并方法作为归并排序,从三个序列中获取每个丑数 子序列。 每一步我们都选择最小的一步,然后再向前迈一步。

public class UglyNumber {
   public int getNthUglyNumber(int n)
   {
       int ugly[] = new int[n];
       int i2 = 0;
       int i3 = 0;
       int i5 = 0;
       int next_mul_of_2 = 2;
       int next_mul_of_3 = 3;
       int next_mul_of_5 = 5;
       int next_ugly_num = 1;
       ugly[0] = 1;
       for(int i = 1; i < n; i++)
       {
           next_ugly_num = Math.min(next_mul_of_2,Math.min(next_mul_of_3,next_mul_of_5));
           ugly[i] = next_ugly_num;
           if(next_ugly_num == next_mul_of_2)
           {
               i2 = i2 + 1;
               next_mul_of_2 = ugly[i2] * 2;
           }
           if(next_ugly_num == next_mul_of_3)
           {
               i3 = i3 + 1;
               next_mul_of_3 = ugly[i3] * 3;
           }
           if(next_ugly_num == next_mul_of_5)
           {
               i5 = i5 + 1;
               next_mul_of_5 = ugly[i5]*5;
           }
       }
       return next_ugly_num;
   }
}

下面是工作方式的演示,求第150个丑数

initialize
   ugly[] =  | 1 |
   i2 =  i3 = i5 = 0;

First iteration
   ugly[1] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
            = Min(2, 3, 5)
            = 2
   ugly[] =  | 1 | 2 |
   i2 = 1,  i3 = i5 = 0  (i2 got incremented ) 

Second iteration
    ugly[2] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
             = Min(4, 3, 5)
             = 3
    ugly[] =  | 1 | 2 | 3 |
    i2 = 1,  i3 =  1, i5 = 0  (i3 got incremented ) 

Third iteration
    ugly[3] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
             = Min(4, 6, 5)
             = 4
    ugly[] =  | 1 | 2 | 3 |  4 |
    i2 = 2,  i3 =  1, i5 = 0  (i2 got incremented )

Fourth iteration
    ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
              = Min(6, 6, 5)
              = 5
    ugly[] =  | 1 | 2 | 3 |  4 | 5 |
    i2 = 2,  i3 =  1, i5 = 1  (i5 got incremented )

Fifth iteration
    ugly[4] = Min(ugly[i2]*2, ugly[i3]*3, ugly[i5]*5)
              = Min(6, 6, 10)
              = 6
    ugly[] =  | 1 | 2 | 3 |  4 | 5 | 6 |
    i2 = 3,  i3 =  2, i5 = 1  (i2 and i3 got incremented )

Will continue same way till I < 150
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值