2021年01月26日 周二 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】
1. 题目简介
2. 三指针法
以下题解是在大佬 不是秒针 的评论中摘录的,非常感谢!
在已有的丑数序列上每一个数都必须乘2, 乘3, 乘5, 这样才不会漏掉某些丑数。假设已有的丑数序列为[1, 2, 3, …, n1, n2],如果单纯的让每个丑数乘2, 乘3, 乘5顺序排列的话肯定是不对的,因为后面乘2的数据可能会比前面乘3乘5的数据要小,那这个乘2的数应该排在他们的前面, 同理乘3也是。
解决办法就是记录每个丑数是否已经被乘2, 乘3, 乘5了,具体的做法是:设置3个索引a、b、c,分别记录前几个数已经被乘2, 乘3, 乘5了,比如a表示前(a-1)个数都已经乘过一次2了,下次应该乘2的是第a个数;b表示前(b-1)个数都已经乘过一次3了,下次应该乘3的是第b个数;c表示前(c-1)个数都已经乘过一次5了,下次应该乘5的是第c个数。那么,下一个丑数一定是第a个丑数乘2, 第b个丑数乘3, 第c个丑数乘5,三者中最小的那个数。然后,a、b、c哪个数在计算当前丑数时被使用了,就自加1。
代码如下:
class Solution {
public:
int nthUglyNumber(int n) {
int a = 0, b = 0, c = 0;
vector<int> dp(n,1);
for(int i=1;i<n;++i){
int n2 = dp[a]*2, n3 = dp[b]*3, n5 = dp[c]*5;
dp[i] = min(min(n2,n3),n5);
if(dp[i]==n2) ++a;
if(dp[i]==n3) ++b;
if(dp[i]==n5) ++c;
}
return dp[n-1];
}
};
- 时间复杂度: O ( n ) O\left( {n} \right) O(n)
- 空间复杂度: O ( n ) O\left( {n} \right) O(n)
参考文献
《剑指offer 第二版》
https://leetcode-cn.com/problems/chou-shu-lcof/solution/mian-shi-ti-49-chou-shu-dong-tai-gui-hua-qing-xi-t/