Topic
- Math
- Dynamic Programming
- Heap
Description
https://leetcode.com/problems/ugly-number-ii/
Analysis
方法一:遍历自然数,逐个判断是否是丑数。这方法很低效。
方法二:动态数组。
We have an array k of first n ugly number. We only know, at the beginning, the first one, which is 1. Then
k[1] = min( k[0]x2, k[0]x3, k[0]x5). The answer is k[0]x2. So we move 2’s pointer to 1. Then we test:
k[2] = min( k[1]x2, k[0]x3, k[0]x5). And so on. Be careful about the cases such as 6, in which we need to forward both pointers of 2 and 3.
x here is multiplication.
方法三:用使用堆。
方法四:使用红黑树。
Submission
import java.util.PriorityQueue;
import java.util.TreeSet;
public class UglyNumberII {
public int nthUglyNumber1(int n) {
if (n < 1 || n > 1690)
throw new IllegalArgumentException();
int index = 0, result = 1;
while (true) {
if (isUgly(result))
index++;
if (index < n) {
result++;
} else
break;
}
return result;
}
private boolean isUgly(int num) {
for (int i = 2; i < 6 && num > 0; i++)
while (num % i == 0)
num /= i;
return num == 1;
}
public int nthUglyNumber2(int n) {
if (n < 1 || n > 1690)
throw new IllegalArgumentException();
int[] uglyNumbers = new int[n];
uglyNumbers[0] = 1;
int index2 = 0, index3 = 0, index5 = 0, uglyNumbersIndex = 1;
while (uglyNumbersIndex < n) {
int maybeNextUglyNumber2 = uglyNumbers[index2] * 2, //
maybeNextUglyNumber3 = uglyNumbers[index3] * 3, //
maybeNextUglyNumber5 = uglyNumbers[index5] * 5;
int min = min(maybeNextUglyNumber2, maybeNextUglyNumber3, maybeNextUglyNumber5);
uglyNumbers[uglyNumbersIndex++] = min;
if (maybeNextUglyNumber2 == min)
index2++;
if (maybeNextUglyNumber3 == min)
index3++;
if (maybeNextUglyNumber5 == min)
index5++;
}
return uglyNumbers[n - 1];
}
private int min(int a, int b, int c) {
return Math.min(Math.min(a, b), c);
}
public int nthUglyNumber3(int n) {
if (n == 1)
return 1;
PriorityQueue<Long> q = new PriorityQueue<>();
q.add(1l);
for (long i = 1; i < n; i++) {
long tmp = q.poll();
while (!q.isEmpty() && q.peek() == tmp)// 去重
tmp = q.poll();
q.add(tmp * 2);
q.add(tmp * 3);
q.add(tmp * 5);
}
return q.poll().intValue();
}
public int nthUglyNumber4(int n) {
TreeSet<Long> ans = new TreeSet<>();
ans.add(1L);
for (int i = 0; i < n - 1; ++i) {
long first = ans.pollFirst();
ans.add(first * 2);
ans.add(first * 3);
ans.add(first * 5);
}
return ans.first().intValue();
}
}
Test
import static org.junit.Assert.*;
import org.junit.Test;
public class UglyNumberIITest {
@Test
public void test() {
UglyNumberII obj = new UglyNumberII();
assertEquals(12, obj.nthUglyNumber1(10));
assertEquals(12, obj.nthUglyNumber2(10));
assertEquals(12, obj.nthUglyNumber3(10));
assertEquals(12, obj.nthUglyNumber4(10));
}
}