I 题目:
Write a program to check whether a given number is an ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5
. For example, 6, 8
are ugly while 14
is not ugly since it includes another prime factor 7
.
Note that 1
is typically treated as an ugly number.
解答:
如果某个数是丑数,那么它一定可以不断被 2 或者 3 或者 5 整除,然后除以之后的结果依然满足丑数的条件。
不断循环,直到这个数不再变化。此时如果是 1 则是丑数,否则不是。
class Solution { public: bool isUgly(int num) { if(num == 1 || num == 2 || num == 3 || num == 5) return true; int tmp = 0; while(tmp != num) { tmp = num; if(num % 2 == 0) num = num / 2; if(num % 3 == 0) num = num / 3; if(num % 5 == 0) num = num / 5; } if(tmp == 1) return true; else return false; } };
II 题目:
Write a program to find the n
-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5
. For example,1, 2, 3, 4, 5, 6, 8, 9, 10, 12
is the sequence of the first 10
ugly numbers.
Note that 1
is typically treated as an ugly number.
查看 hint,可以知道每个出现在序列中的数,都是前面某个数乘以系数2,3或5之后的结果。
于是,记录上一次乘以2,3或5之前的那个数pos2, pos3, pos5,然后比较乘以系数之后的结果的最小值,放在这个序列。然后即时更新pos2, pos3, pos5。
这是我第一个版本的错误代码:
class Solution { public: int nthUglyNumber(int n) { if(n <= 0) return 0; int* nums = new int[n + 1]; nums[0] = 0; nums[1] = 1; int pos2, pos3, pos5; pos2 = pos3 = pos5 = 1; for(int i = 2; i <= n; i++) { if(nums[pos2]*2 <= nums[pos3]*3 && nums[pos2]*2 <= nums[pos5]*5) { nums[i] = nums[pos2]*2; pos2 = i; } else if(nums[pos3]*3 <= nums[pos2]*2 && nums[pos3]*3 <= nums[pos5]*5) { nums[i] = nums[pos3]*3; pos3 = i; } else { nums[i] = nums[pos5]*5; pos5 = i; } } return nums[n]; } };这个版本的错误在于:
修改之后的 AC 版本:
class Solution { public: int nthUglyNumber(int n) { if(n <= 0) return 0; int* nums = new int[n + 1]; nums[0] = 0; nums[1] = 1; int pos2, pos3, pos5; pos2 = pos3 = pos5 = 1; for(int i = 2; i <= n; i++) { if(nums[pos2]*2 <= nums[pos3]*3 && nums[pos2]*2 <= nums[pos5]*5) { nums[i] = nums[pos2]*2; pos2 ++; if(nums[i] % 3 == 0) pos3 ++; if(nums[i] % 5 == 0) pos5 ++; } else if(nums[pos3]*3 <= nums[pos2]*2 && nums[pos3]*3 <= nums[pos5]*5) { nums[i] = nums[pos3]*3; pos3 ++; if(nums[i] % 2 == 0) pos2 ++; if(nums[i] % 5 == 0) pos5 ++; } else { nums[i] = nums[pos5]*5; pos5 ++; if(nums[i] % 2 == 0) pos2 ++; if(nums[i] % 3 == 0) pos3 ++; } } return nums[n]; } };
Write a program to find the nth super ugly number.
Super ugly numbers are positive numbers whose all prime factors are in the given prime listprimes
of size k
. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32]
is the sequence of the first 12 super ugly numbers givenprimes
= [2, 7, 13, 19]
of size 4.
Note:
(1) 1
is a super ugly number for any given primes
.
(2) The given numbers in primes
are in ascending order.
(3) 0 < k
≤ 100, 0 < n
≤ 106, 0 < primes[i]
< 1000.
思路与上一题相同。不过,此时优化了一下,不需要每次取整,而是更准确的判断潜在乘积而去重:
class Solution { public: int nthSuperUglyNumber(int n, vector<int>& primes) { int k = primes.size(); vector<int> pos(k, 0); vector<int> ugly(n, INT_MAX); ugly[0] = 1; for(int i = 1; i< n; i++) { for(int j = 0; j < k; j++) ugly[i] = (ugly[i] < ugly[pos[j]] * primes[j]) ? ugly[i] : (ugly[pos[j]] * primes[j]); for(int j = 0; j < k; j++) if(ugly[i] == ugly[pos[j]] * primes[j]) pos[j]++; } return ugly[n - 1]; } };