剑指offer 50. 丑数(三指针法,比动态规划更好理解)

2021年01月26日 周二 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】



1. 题目简介

剑指 Offer 49. 丑数
在这里插入图片描述

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/

猜你喜欢

转载自blog.csdn.net/m0_37433111/article/details/113182468