剑指offer32_丑数_题解

丑数

题目描述

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

示例1

输入

7

返回值

8

分析

小顶堆的方法是先存再排,dp的方法则是先排再存

方案一:小根堆

丑数是另一个丑数乘以2、3或者5的结果。

创建一个小根堆,初始时压入元素1

由于优先队列具有自动排序的功能,只要每次生成新的丑数都由堆顶元素(当前最小的丑数)乘以2、3或者5得到的,就能保证堆顶元素组成的序列即为丑数的有序序列。

代码

/**
1.时间复杂度:O(nlogn)
2.空间复杂度:O(n)
**/
class Solution
{
public:
    int GetUglyNumber_Solution(int index)
    {
        vector<int> fac = {2, 3, 5};
        priority_queue<int, vector<int>, greater<int>> q;
        q.push(1);
        int top = 0;
        for (int i = 0; i < index; i++)
        {
            top = q.top();
            for (const int k : fac)
            {
                q.push(top * k);
            }
            //去重
            while (q.top() == top)
                q.pop();
        }
        return top;
    }
};

方案二:动态规划

参考链接

https://leetcode-cn.com/problems/chou-shu-lcof/solution/mian-shi-ti-49-chou-shu-dong-tai-gui-hua-qing-xi-t/

代码

/**
1.时间复杂度:O(n)
2.空间复杂度:O(n)
**/
class Solution
{
public:
    int GetUglyNumber_Solution(int index)
    {
        int a = 0, b = 0, c = 0;
        vector<int> dp(index, 0);
        dp[0] = 1;//dp[i]代表第i+1个丑数
        for (int i = 1; i < index; i++)
        {
            int n2 = dp[a] * 2, n3 = dp[b] * 3, n5 = dp[c] * 5;
            dp[i] = min(min(n2, n3), n5);
            //每轮计算dp[i]以后,需要更新索引a,b,c的值
            // 第a个数已经通过乘2得到了一个新的丑数,那下个需要通过乘2得到一个新的丑数的数应该是第(a+1)个数
            if (dp[i] == n2)
                a++;
            // 第 b个数已经通过乘3得到了一个新的丑数,那下个需要通过乘3得到一个新的丑数的数应该是第(b+1)个数
            if (dp[i] == n3)
                b++;
            // 第 c个数已经通过乘5得到了一个新的丑数,那下个需要通过乘5得到一个新的丑数的数应该是第(c+1)个数
            if (dp[i] == n5)
                c++;
        }
        return dp[index - 1];
    }
};
posted @ 2021-01-11 22:09  RiverCold  阅读(62)  评论(0编辑  收藏  举报