JAVA算法:求丑数—动态规划

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/seagal890/article/details/89603049

JAVA算法:求丑数—动态规划(Ugly Numbers)

丑数是唯一的因子是2、3或5的数字。

序列1,2,3,4,5,6,8,9,10,12,15,…显示前11个丑数。按照惯例,1包括在内。

给定一个数字n,你的任务就是找出第n个丑数。

实例:

输入:n=7

输出:8

输入:n=10

输出:12

输入:n=15

输出:24

扫描二维码关注公众号,回复: 6079572 查看本文章

输入:n=150

输出:5832

算法设计1:

遍历访问所有的正整数,直到丑数计数小于n(如果整数丑数小于增量丑数计数)。

要检查一个数字是否是丑数,用2、3和5的最大可除乘方除该数字,如果该数字变为1,则它是一个丑数,否则不是。

例如,让我们看看如何检查300是否为丑数。4可以被因子2(最大因子)除尽,将300除以4以后得到75。3可以被因子3(最大因子)除尽,将75除以3得到25。25可以被因子5(最大因子)除尽,所以25除以25得到1。因为我们最后得到1,所以300是一个丑数。

package com.bean.algorithm.basic;

public class UglyNumbers {
	// Java program to find nth ugly number
	/*
	 * This function divides a by greatest divisible power of b
	 */
	static int maxDivide(int a, int b) {
		while (a % b == 0)
			a = a / b;
		return a;
	}

	/*
	 * Function to check if a number is ugly or not
	 */
	static int isUgly(int no) {
		no = maxDivide(no, 2);
		no = maxDivide(no, 3);
		no = maxDivide(no, 5);

		return (no == 1) ? 1 : 0;
	}

	/*
	 * Function to get the nth ugly number
	 */
	static int getNthUglyNo(int n) {
		int i = 1;

		// ugly number count
		int count = 1;

		// check for all integers
		// until count becomes n
		while (n > count) {
			i++;
			if (isUgly(i) == 1)
				count++;
		}
		return i;
	}

	/*
	 * Driver program to test above functions
	 */
	public static void main(String args[]) {
		int no = getNthUglyNo(150);
		System.out.println("150th ugly " + "no. is " + no);
	}
}

程序运行结果:

150th ugly no. is 5832

算法设计 2 (动态规划)

丑数的序列为 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, …
因为每个数字只能除以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。

然后我们使用相似的合并方法作为合并排序,从三个子序列中得到每个丑数。每一步我们都选择最小的一步,然后再往前走一步。

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

举例,让我们看看上面的伪代码如何工作的。

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


 

package com.bean.algorithm.basic;

public class UglyNumbers {
	// Java program to find nth ugly number

	/* Function to get the nth ugly number */
	int getNthUglyNo(int n) {
		int ugly[] = new int[n]; // To store ugly numbers
		int i2 = 0, i3 = 0, i5 = 0;
		int next_multiple_of_2 = 2;
		int next_multiple_of_3 = 3;
		int next_multiple_of_5 = 5;
		int next_ugly_no = 1;

		ugly[0] = 1;

		for (int i = 1; i < n; i++) {
			next_ugly_no = Math.min(next_multiple_of_2, Math.min(next_multiple_of_3, next_multiple_of_5));

			ugly[i] = next_ugly_no;
			if (next_ugly_no == next_multiple_of_2) {
				i2 = i2 + 1;
				next_multiple_of_2 = ugly[i2] * 2;
			}
			if (next_ugly_no == next_multiple_of_3) {
				i3 = i3 + 1;
				next_multiple_of_3 = ugly[i3] * 3;
			}
			if (next_ugly_no == next_multiple_of_5) {
				i5 = i5 + 1;
				next_multiple_of_5 = ugly[i5] * 5;
			}
		} /* End of for loop (i=1; i<n; i++) */
		return next_ugly_no;
	}

	/* Driver program to test above functions */
	public static void main(String args[]) {
		int n = 150;
		UglyNumbers obj = new UglyNumbers();
		System.out.println(obj.getNthUglyNo(n));
	}
}

程序输出结果:

5832

猜你喜欢

转载自blog.csdn.net/seagal890/article/details/89603049