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
输入: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