题目地址:Ugly Number II - LeetCode
Write a program to find the n-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5.
Example:
Input: n = 10
Output: 12
Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.
Note:
1 is typically treated as an ugly number.
n does not exceed 1690.
这道题目是经典的求丑数的题目。
比较容易想到的方法是使用队列,然后不断pop,把当前的数乘以2,3,5。
Python解法如下:
class Solution:
def nthUglyNumber(self, n: int) -> int:
count = 0
l = [1]
for i in range(0, n-1):
temp = l.pop(0)
for j in [2,3,5]:
if j*temp not in l:
l.append(j*temp)
l.sort()
return l[0]
这个做法的缺点是比较慢,因为每次都要做很多次判断。
用最小堆和set减少判断次数,时间消耗显著减少。
from heapq import heappop, heappush
class Solution:
def nthUglyNumber(self, n: int) -> int:
count = 0
heap = []
heappush(heap, 1)
see=set(heap)
for i in range(0, n-1):
temp = heappop(heap)
for j in [2,3,5]:
if j*temp not in see:
see.add(j*temp)
heappush(heap, j*temp)
return heappop(heap)
更快的,不用排序的解法如下:
class Solution:
def nthUglyNumber(self, n: int) -> int:
if n == 1:
return 1
l1 = [2]
l2 = [3]
l3 = [5]
for i in range(0, n-2):
temp = min(l1[0], l2[0], l3[0])
if temp == l1[0]:
l1.pop(0)
l1.append(temp*2)
l2.append(temp*3)
l3.append(temp*5)
elif temp == l2[0]:
l2.pop(0)
l2.append(temp*3)
l3.append(temp*5)
else:
l3.pop(0)
l3.append(temp*5)
return min(l1[0], l2[0], l3[0])
上面这个解法也有问题,问题是需要pop,而pop操作是比较花费时间的,官方提供的动态规划的解法如下:
class Solution:
def nthUglyNumber(self, n: int) -> int:
if n == 1:
return 1
nums = [1]
i2 = i3 = i5 = 0
for i in range(0, n):
ugly = min(nums[i2] * 2, nums[i3] * 3, nums[i5] * 5)
nums.append(ugly)
if ugly == nums[i2] * 2:
i2 += 1
if ugly == nums[i3] * 3:
i3 += 1
if ugly == nums[i5] * 5:
i5 += 1
return nums[n-1]
C++解法如下:
class Solution {
public:
int nthUglyNumber(int n) {
if(n <= 0) return false; // get rid of corner cases
if(n == 1) return true; // base case
int t2 = 0, t3 = 0, t5 = 0; //pointers for 2, 3, 5
vector<int> k(n);
k[0] = 1;
for(int i = 1; i < n ; i ++)
{
k[i] = min(k[t2]*2,min(k[t3]*3,k[t5]*5));
if(k[i] == k[t2]*2) t2++;
if(k[i] == k[t3]*3) t3++;
if(k[i] == k[t5]*5) t5++;
}
return k[n-1];
}
};