Write a program to check whether a given number is an ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5
. For example, 6, 8
are ugly while 14
is not ugly since it includes another prime factor 7
.
1
is typically treated as an ugly number
判断一个数字是不是丑数
public boolean isUgly(int num) {
// num & 1 == 0
if (num == 0)
return false;
while (num % 2 == 0)
num = num >> 1;
while (num % 3 == 0)
num /= 3;
while (num % 5 == 0)
num /= 5;
return num == 1;
}
Write a program to find the n
-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5
. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12
is the sequence of the first 10
ugly numbers.
Note that 1
is typically treated as an ugly number, and n does not exceed 1690.
寻找第n个丑数(丑数只有2,3,5的最小因子)
动态规划:
public int nthUglyNumber(int n) {
int[] dp = new int[n];
dp[0] = 1;
// 2, 3, 5最小丑数
int f2 = 2, f3 = 3, f5 = 5;
// f2, f3, f5对应最小值的下标
int ix2 = 0, ix3 = 0, ix5 = 0;
for (int i = 1; i < n; ++i) {
int min = Math.min(Math.min(f2, f3), f5);
// dp[i]设置为最小值
dp[i] = min;
// 下方if只能执行一个,求出下一个丑数可能为最小值,
// 用于和其他未改变两个的值大小
// 同时更新对应的下标
// 注意ix2,3,5是从下标0开始
// 若为1,则是后++
if (min == f2)
f2 = 2 * dp[++ix2];
if (min == f3)
f3 = 3 * dp[++ix3];
if (min == f5)
f5 = 5 * dp[++ix5];
}
return dp[n - 1];
}
public int nthUglyNumber(int n) {
int[] dp = new int[n];
// 第一个丑数是1
dp[0] = 1;
// 对应2,3,5的下标
int idx2 = 0;
int idx3 = 0;
int idx5 = 0;
int counter = 1;
while (counter < n) {
// 找出数组dp[idx2]*2、
//dp[idx3]*3、dp[idx5]*5的最小值,
// 最小值即为下一个丑数,同时更新最小值对应的下标,
// 如果多个数字同时为最小值,则它们的下标都要更新
int min = minOf
(dp[idx2] * 2,
dp[idx3] * 3,
dp[idx5] * 5);
if (min == dp[idx2] * 2) {
idx2++;
}
if (min == dp[idx3] * 3) {
idx3++;
}
if (min == dp[idx5] * 5) {
idx5++;
}
dp[counter] = min;
counter++;
}
return dp[n - 1];
}
private int minOf(int a, int b, int c) {
int temp = a < b ? a : b;
return temp < c ? temp : c;
}
// 使用队列的动态规划
// O(n) (might be more) time, O(3n) space
public int nthUglyNumber(int n) {
Queue q1 = new LinkedList<>();
Queue q2 = new LinkedList<>();
Queue q3 = new LinkedList<>();
// 把第一个丑数加进去
q1.offer(1);
q2.offer(1);
q3.offer(1);
int m = 0;
for (int i = 0; i < n; ++i) {
m = Math.min(Math.min(q1.peek(), q2.peek()), q3.peek());
// i=0时,队列头部元素都为1,此时三个队列同时更新最小值
if (m == q1.peek())
q1.poll();
if (m == q2.peek())
q2.poll();
if (m == q3.peek())
q3.poll();
q1.offer(2 * m);
q2.offer(3 * m);
q3.offer(5 * m);
}
return m;
}
参考:https://leetcode.com/problems/ugly-number-ii/#/solutions