丑陋的数字 - DP方法

时间:2017-12-31 14:24:48

标签: algorithm dynamic-programming

问题: 丑陋的数字是唯一的素数因子是2,3或5的数字。序列1,2,3,4,5,6,8,9,10,12,15 ......显示前11个丑陋的数字。按照惯例,包括1。

给定一个数字n,任务是找到n’th丑陋的数字。 (https://www.geeksforgeeks.org/ugly-numbers/

回答:上述链接中的动态编程方法

伪码:

1 Declare an array for ugly numbers:  ugly[n]
2 Initialize first ugly no:  ugly[0] = 1
3 Initialize three array index variables i2, i3, i5 to point to 
   1st element of the ugly array: 
        i2 = i3 = i5 =0; 
4 Initialize 3 choices for the next ugly no:
         next_mulitple_of_2 = ugly[i2]*2;
         next_mulitple_of_3 = ugly[i3]*3
         next_mulitple_of_5 = ugly[i5]*5;
5 Now go in a loop to fill all ugly numbers till 150:
For (i = 1; i < 150; i++ ) 
{
    /* These small steps are not optimized for good 
      readability. Will optimize them in C program */
    next_ugly_no  = Min(next_mulitple_of_2,
                        next_mulitple_of_3,
                        next_mulitple_of_5); 

    ugly[i] =  next_ugly_no       

    if (next_ugly_no  == next_mulitple_of_2) 
    {             
        i2 = i2 + 1;        
        next_mulitple_of_2 = ugly[i2]*2;
    } 
    if (next_ugly_no  == next_mulitple_of_3) 
    {             
        i3 = i3 + 1;        
        next_mulitple_of_3 = ugly[i3]*3;
     }            
     if (next_ugly_no  == next_mulitple_of_5)
     {    
        i5 = i5 + 1;        
        next_mulitple_of_5 = ugly[i5]*5;
     } 

}/* end of for loop */ 
6.return next_ugly_no

疑惑:

在这种情况下,我不了解DP方法。

  1. 有哪些子问题?
  2. 这种情况下的递归是什么?
  3. 子问题如何重叠?
  4. 为什么我们要跟踪当前丑陋的数字?为什么不经历2,3,5的倍数,每个点保持最小。

    喜欢2,3,5。然后4,3,5,然后4,6,5..keeps增加每个的倍数。

  5. 相关问题:nth ugly number(我试着通过答案,但我对上面提到的问题感到困惑。)

3 个答案:

答案 0 :(得分:2)

  1. subproblems:查找所有数字为2的倍数,3,为5
  2. 递归:使用以前的丑陋数字来计算未来的丑陋数字。动态编程解决方案通过使用存储来缩短递归的需要。
  3. 重叠:输出需要按数字顺序排列,因此不清楚哪个子问题会按顺序生成下一个。
  4. 为什么要跟踪:如果不重复使用以前的丑陋数字,你只能获得指数结果2 ^ n,3 ^ n,5 ^ n
  5. 进一步优化:通过修剪丑陋的数组以取消设置任何<1的值来实现空间减少。 min(i2,i3,i5)因为它们永远不会再被需要了。

答案 1 :(得分:0)

这是我按照子问题来表达问题的方式:

  

第i个丑数是通过将另一个丑数(严格小于第i个)乘以2、3或5来获得的。第一个丑数是1。

因此:

// dp[i] ... the i-th ugly number
dp[1] = 1;
i2 = i3 = i5 = 1;
for i in 2 .. n:
  dp[i] = min(2*dp[i2], 3*dp[i3], 5*dp[i5]);
  // where: 1 <= i2, i3, i5 < i

  // update i2, i3, i5 - (this part is tedious)
return dp[n];

以下是提出的算法的运行方式: Algorithm animation

答案 2 :(得分:0)

t = int(input())

# function to get all the numbers with prime factors within a given range

def prime(n):
    global l
    a = []
    i = 1
    while (i <= n):
        k = 0
        if (n % i == 0):
            j = 1
            while (j <= i):
                if (i % j == 0):
                    k = k + 1
                j = j + 1
            if (k == 2):
                a.append(i)
        i = i + 1
    check(a)

#function to filter all non-ugly numbers

def check(a):
    if (all(x in l for x in a)):
        everything.append(n)

# main code

while t >0:
    h = int(input())
    l = [2, 3, 5]
    everything = []
    for n in range(1, h**2):
        prime(n)
    print(everything[h - 1])
    t-=1