题目链接

LeetCode

题目描述

把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。例如 6、8 都是丑数,但 14 不是,因为它包含因子 7。习惯上我们把 1 当做是第一个丑数。求按从小到大的顺序的第 N 个丑数。

解题思路

丑数的递推性质: 丑数只包含因子 2,3,5 ,因此有 “丑数 = 某较小丑数 × 某因子” (例如:10=5×2)。
image.png
49. 丑数* - 图2
image.png

  1. class Solution {
  2. public:
  3. int Ugly[1692];
  4. Solution(){
  5. Ugly[1] = 1;
  6. // t2 就是乘以2的丑数,t3就是乘以3的丑数,t5就是乘以5的丑数
  7. int t2 = 1, t3 = 1, t5 = 1;
  8. for(int i = 2; i <= 1690; i++)
  9. {
  10. // 三个丑数中选取最小的(2,3,5) 作为下一个丑数
  11. Ugly[i] = min(Ugly[t2]*2, min(Ugly[t3]*3, Ugly[t5]*5));
  12. // 第a个数已经通过乘2得到了一个新的丑数,那下个需要通过乘2得到一个新的丑数的数应该是第(a+1)个数
  13. if(Ugly[i] == Ugly[t2] * 2) t2++;
  14. // 第 b个数已经通过乘3得到了一个新的丑数,那下个需要通过乘3得到一个新的丑数的数应该是第(b+1)个数
  15. if(Ugly[i] == Ugly[t3] * 3) t3++;
  16. // 第 c个数已经通过乘5得到了一个新的丑数,那下个需要通过乘5得到一个新的丑数的数应该是第(c+1)个数
  17. if(Ugly[i] == Ugly[t5] * 5) t5++;
  18. }
  19. }
  20. int nthUglyNumber(int n) {
  21. if(n==0)
  22. return 0;
  23. return Ugly[n];
  24. }
  25. };
  1. class Solution {
  2. int[] ugly = new int[1691];
  3. Solution(){
  4. ugly[1] = 1;
  5. int a = 1, b = 1, c = 1;
  6. for(int i = 2; i < 1691; ++i){
  7. int minVal = Math.min(ugly[a]*2,Math.min(ugly[b]*3,ugly[c]*5));
  8. if(minVal == ugly[a]*2){
  9. ++a;
  10. }
  11. if(minVal == ugly[b]*3){
  12. ++b;
  13. }
  14. if(minVal == ugly[c]*5){
  15. ++c;
  16. }
  17. ugly[i] = minVal;
  18. }
  19. }
  20. public int nthUglyNumber(int n) {
  21. return ugly[n];
  22. }
  23. }
  • 时间复杂度 O(N): 其中 N=n ,动态规划需遍历计算 dp 列表。
  • 空间复杂度 O(N) : 长度为 N 的 dp 列表使用 O(N) 的额外空间。