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 first10
ugly numbers.
Note:
1
is typically treated as an ugly number.n
does not exceed 1690.
Hint:
- The naive approach is to call
isUgly()
for every number until you reach then
-th one. Most numbers are not ugly. Try to focus your effort on generating only the ugly ones. - An ugly number must be multiplied by either 2, 3, or 5 from a smaller ugly number.
- The key is how to maintain the order of the ugly numbers. Try a similar approach of merging from three sorted lists: L_1L1, L_2L2, and L_3L3.
- Assume you have U_kUk, the k^{th}kth ugly number. Then U_{k+1}Uk+1 must be Min(L_1 * 2, L_2 * 3, L_3 * 5)Min(L1∗2,L2∗3,L3∗5).
我信你个鬼,hint1我试了,果然超时。
分析
根据提示中的信息,我们知道丑陋序列可以拆分成3个子序列:
- 1x2, 2x2, 3x2, 4x2, 5x2, ...
- 1x3, 2x3, 3x3, 4x3, 5x3, ...
- 1x5, 2x5, 3x5, 4x5, 5x5, ...
注意是1,2,3,4,5,6,8,9,10.。。。而不是1,2,3,4,5,6,7,8,9,,,,,,所以才能用存在数组里的数继续做
每次从三个列表中取出当前最小的那个加入序列,直到第n
个为止。
public int nthUglyNumber(int n) { int[] nums = new int[n]; int index2 = 0, index3 = 0, index5 = 0; nums[0] = 1; for(int i = 1; i < nums.length; i++){ nums[i] = Math.min(nums[index2] * 2, Math.min(nums[index3] * 3, nums[index5] * 5)); if(nums[i] == nums[index2] * 2) index2++; if(nums[i] == nums[index3] * 3) index3++; if(nums[i] == nums[index5] * 5) index5++; } return nums[n - 1]; }
总结:
Ugly numbers can be created from2, 3, 5, then
- 1x2, 2x2, 3x2, 4x2, 5x2, ...
- 1x3, 2x3, 3x3, 4x3, 5x3, ...
- 1x5, 2x5, 3x5, 4x5, 5x5, ...
Since it was made of these 3 factors, we can use 3 variables to keep track the index of each factor. nums[index2/3/5] * 2/3/5