1. 263. 丑数
给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。
丑数 就是只包含质因数 2、3 或 5 的正整数。
示例 1:
输入:n = 6
输出:true
解释:6 = 2 × 3
示例 3:
输入:n = 14
输出:false
解释:14 不是丑数,因为它包含了另外一个质因数 7 。
题解
这个题其实很简单。因为丑数的概念就必须是只有2、3、5这三个质因子的数。
那它需要满足什么条件那
- 如果这个数是2的倍数则就除2
- 如果是3的倍数则就除3
- 如果是5的倍数就除5
如果这个是丑数的话,那这样剩下的数一定是1。
证明
如果这个数不是1,那么也不能是2,3,5的倍数。那么他就必须是7, 11 这种的质因子。
这与它是丑数相悖。所以一定满足上面说的条件,那代码就呼之欲出了
代码
class Solution {
public:
bool isUgly(int n) {
if (n < 1)return false;
while(n % 2 == 0) n /= 2;
while(n % 3 == 0) n /= 3;
while(n % 5 == 0) n /= 5;
return n == 1;
}
};
2. 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 通常被视为丑数。
题解
这个题和上面的区别就是要我们找出第n个丑数。
实际上我们可以先列表找一个感觉1、2、3、4、5、6、8、9、10、12 .....
我们把这个序列称为S那我们要返回的就是S[n]
我们用S2表示只包含质因子2的数。S3表示只包含质因子3的数。S5表示只包含质因子为5的数
S2 : 2, 4, 6 , 8 , ....
S3 : 3, 6, 9 , 12, 15 ...
S5 : 5, 10, 15, ....
可以发现S数组的数就是从S2,S3,S5并操作得到的(在并上一个1)
另外一个特性就是 S2 = 2 * S, S3 = 3 * S , S5 = 5 * S
这样就可以用三个指针指向1这个数。
然后对指针往下移动。依次取三个指针的最小值。最后就可以得到S序列,那代码也就好写了
代码
class Solution {
public:
int nthUglyNumber(int n) {
vector<int>q(1,1); // 表示只有1这个数,是第一个丑数
for (int i = 0, j = 0, k = 0; q.size() < n; ) {
int t = min(q[i] * 2, min(q[j] * 3, q[k] * 5));
if (t == q[i] * 2) i++;
if (t == q[j] * 3) j++;
if (t == q[k] * 5) k++;
q.push_back(t);
}
return q[n - 1];
}
};
3. 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] 中。
题解
这个题和上面的题,非常类似哦。
只不过是上面的要求是只能有2,3,5而这个题目给了一个要求是只能包含特定序列的质数
因此这里用了一个小根堆来存储相关的最小值。这样每次logk
就可以了
这里的指针移动就是向堆内加入一个新的元素
- 这里利用这样的一个堆存储{value, position} position为这个值是由数组中哪个值更新的
- 然后算除当前值是由之前的值如何更新的。因为一定是会??一个集合内的素数
- 随后将这个集合指针往下移动那就是入堆一个{p * q[idx + 1], idx + 1}
代码
class Solution {
public:
int nthSuperUglyNumber(int n, vector<int>& primes) {
typedef pair<int,int> PII;
priority_queue<PII, vector<PII>, greater<PII>> heap;
for (auto e : primes) {
heap.push({e, 0});
}
vector<int>q(n);
q[0] = 1;
for (int i = 1; i < n; ) {
auto t = heap.top();
heap.pop();
if (t.first != q[i - 1])q[i++] = t.first;
int idx = t.second;
int p = t.first / q[idx];
heap.push({p * q[idx + 1], idx+1});
}
return q[n - 1];
}
};