263. 丑数 丑数 就是只包含质因数 2、3 和 5 的正整数。
给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。
示例 1:
输入:n = 6 输出:true 解释:6 = 2 × 3 示例 2:
输入:n = 1 输出:true 解释:1 没有质因数,因此它的全部质因数是 {2, 3, 5} 的空集。习惯上将其视作第一个丑数。 示例 3:
输入:n = 14 输出:false 解释:14 不是丑数,因为它包含了另外一个质因数 7 。
分别对n反复除以质因子2,3,5, 如果最后剩余的值为1,则OK
1 2 3 4 5 6 7 8 9 10 11 12 class Solution {public : bool isUgly (int n) { if (n <= 0 ) return false ; if (n == 1 ) return true ; int factors[3 ] = {2 , 3 , 5 }; for (auto factor : factors) { while (n % factor == 0 ) n = n/factor; } return n == 1 ; } };
264. 丑数 II 给你一个整数 n ,请你找出并返回第 n 个 丑数 。
丑数 就是只包含质因数 2、3 和/或 5 的正整数。
示例 1:
输入:n = 10 输出:12 解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。 示例 2:
输入:n = 1 输出:1 解释:1 通常被视为丑数。
暴力法 直接按自然数顺序遍历isUgly, 但是时间复杂度O(nlogn)太高,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution {public : int nthUglyNumber (int n) { if (n == 1 ) return 1 ; int count = 1 ; int i = 1 ; while (count < n) { i++; if (isUgly (i)) { count++; } } return i; } bool isUgly (int n) { if (n <= 0 ) return false ; if (n == 1 ) return true ; int factors[3 ] = {2 , 3 , 5 }; for (auto factor : factors) { while (n % factor == 0 ) n = n/factor; } return n == 1 ; } };
小顶堆 每次从堆顶取出最小值,然后乘以三个因子后的数加入堆,为了避免重复,可以使用集合过滤。
时间复杂度也是O(nlogn), 但是确能通过OJ了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution {public : int nthUglyNumber (int n) { int factors[3 ] = {2 , 3 , 5 }; unordered_set<long > seen; priority_queue<long , vector<long >, greater<long >> heap; long ans = 1 ; heap.push (ans); seen.insert (ans); long cur = 1 ; for (int i = 0 ; i < n; i++) { cur = heap.top (); heap.pop (); for (auto factor : factors) { long next = cur * factor; if (!seen.count (next)) { seen.insert (next); heap.push (next); } } } return cur; } };
三个数组(或者叫动态规划) dp[i] = min(dp[i-1]*2, dp[i-1]*3, dp[i-1]*5) 初始时候dp[1] = 1; 后面不断的乘以2,3,5分别可以得到3个数组,就是不知道下一次该选谁,所以有三个指针记录当前走到的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution {public : int nthUglyNumber (int n) { int factors[3 ] = {2 , 3 , 5 }; vector<int > dp (n+1 ) ; int p2 = 1 , p3 = 1 , p5 = 1 ; dp[1 ] = 1 ; int pre = 1 , ans = 1 ; for (int i = 2 ; i <= n; i++) { int num2 = dp[p2]*2 , num3 = dp[p3]*3 , num5 = dp[p5]*5 ; dp[i] = min (num2, min (num3, num5)); if (dp[i] == num2) p2++; if (dp[i] == num3) p3++; if (dp[i] == num5) p5++; } return dp[n]; } };
313. 超级丑数 超级丑数 是一个正整数,并满足其所有质因数都出现在质数数组 primes 中。
给你一个整数 n 和一个整数数组 primes ,返回第 n 个 超级丑数 。
题目数据保证第 n 个 超级丑数 在 32-bit 带符号整数范围内。
示例 1:
输入:n = 12, primes = [2,7,13,19] 输出:32 解释:给定长度为 4 的质数数组 primes = [2,7,13,19],前 12 个超级丑数序列为:[1,2,4,7,8,13,14,16,19,26,28,32] 。 示例 2:
输入:n = 1, primes = [2,3,5] 输出:1 解释:1 不含质因数,因此它的所有质因数都在质数数组 primes = [2,3,5] 中。 提示:
1 <= n <= 105 1 <= primes.length <= 100 2 <= primes[i] <= 1000 题目数据 保证 primes[i] 是一个质数 primes 中的所有值都 互不相同 ,且按 递增顺序 排列
思路和普通丑数的处理方式一样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution {public : int nthSuperUglyNumber (int n, vector<int >& primes) { int prime_size = primes.size (); vector<int > pointers (prime_size, 1 ) ; vector<long > tmp_nums (prime_size, 1 ) ; vector<long > dp (n+1 , INT_MAX) ; dp[1 ] = 1 ; for (int i = 2 ; i <=n; i++) { for (int p_index = 0 ; p_index < prime_size; p_index++) { tmp_nums[p_index] = primes[p_index]*dp[pointers[p_index]]; if (tmp_nums[p_index] < dp[i]) dp[i] = tmp_nums[p_index]; } for (int p_index = 0 ; p_index < prime_size; p_index++) { if (dp[i] == tmp_nums[p_index]) { pointers[p_index]++; } } } return dp[n]; } };
1201. 丑数 III 给你四个整数:n 、a 、b 、c ,请你设计一个算法来找出第 n 个丑数。
丑数是可以被 a 或 b 或 c 整除的 正整数 。
示例 1:
输入:n = 3, a = 2, b = 3, c = 5 输出:4 解释:丑数序列为 2, 3, 4, 5, 6, 8, 9, 10… 其中第 3 个是 4。 示例 2:
输入:n = 4, a = 2, b = 3, c = 4 输出:6 解释:丑数序列为 2, 3, 4, 6, 8, 9, 10, 12… 其中第 4 个是 6。 示例 3:
输入:n = 5, a = 2, b = 11, c = 13 输出:10 解释:丑数序列为 2, 4, 6, 8, 10, 11, 12, 13… 其中第 5 个是 10。 示例 4:
输入:n = 1000000000, a = 2, b = 217983653, c = 336916467 输出:1999999984
这题和前面的题,似乎都不太一样,
递推的思路,时间复杂度太高 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution {public : int nthUglyNumber (int n, int a, int b, int c) { int factors[3 ] = {a, b, c}; vector<int > dp (n+2 , INT_MAX) ; int p2 = 1 , p3 = 1 , p5 = 1 ; dp[1 ] = 1 ; int pre = 1 , ans = 1 ; for (int i = 2 ; i <= n+1 ; i++) { int num2 = p2*factors[0 ], num3 = p3*factors[1 ], num5 = p5*factors[2 ]; dp[i] = min (num2, min (num3, num5)); if (dp[i] == num2) p2++; if (dp[i] == num3) p3++; if (dp[i] == num5) p5++; cout << " " << dp[i]; } return dp[n+1 ]; } };
二分 TODO