剑指offer(C++)-JZ49:丑数(算法-其他)

这篇具有很好参考价值的文章主要介绍了剑指offer(C++)-JZ49:丑数(算法-其他)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

剑指offer(C++)-JZ49:丑数(算法-其他),剑指offer,算法,c++

题目描述:

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

数据范围:0≤n≤2000

要求:空间复杂度 O(n) , 时间复杂度 O(n)

示例:

输入:

7

返回值:

8

解题思路:

本题考察算法思维。两种解题思路:

1)优先队列-最小堆

       丑数是含质因子2、3、5的数,从1开始,1乘这三个因数得到的数就是丑数,以此类推,丑数乘因数也是丑数。考虑到这样操作可能会有重复,所以借助map完成去重。再构建优先队列-小顶堆往里面塞入丑数,放入的过程会自动进行排序,排序复杂度在O(log2n)。

       假设获取前n个丑数,就进行n次循环,每次循环将最小的丑数弹出,并放入新的丑数,放入的时候还需要进行重复性判断。

       综合下来,算法时间复杂度为O(nlog2n)。

2)动态规划

       丑数1 2 3 4 5 6 8 9 10等等,每个丑数一定是前面某个数的235倍数,可结合动态规划思想,设置三个步进下标ijk,将已知丑数依次乘235得到后续丑数,在此过程中还需要确保丑数是从小到大放入容器的,即进行最小值比较。

       为了直观些,简单模拟下前面几步的流程:

1)开始ijk均为0,则从数字1开始,丑数后续依次为2 3 5,其中2最小,则i升为1。

2)i为1,即第二个丑数2,用2的2倍也就是4和3 5比较,此时3最小,则j升为1。

3)i和j为1,即用第二个丑数2的2倍3倍,即4和6,和5比较,此时4最小,则i继续升为2。

4)i为2,j为1,k为0,用3的2倍、2的3倍、1的5倍比较,即6 6 4,此时5最小,则k升为1。

5)i为2,j为1,k为1,用3的2倍、2的3倍,2的5倍比较,即6 6 10,此时6最小,i和j同时升1。

       从上述5步可看到全局规律,ijk是从前往后慢慢推进的,结合了动态规划的思想,后续步进以前面为基准,动态扩展后续丑数

       该算法时间复杂度为O(n),也是题目理想解法。

测试代码:

1)优先队列-最小堆

#include <queue>
class Solution {
public:
    // 获取丑数
    int GetUglyNumber_Solution(int index) {
        // 判空
        if(index == 0){
            return 0;
        }
        // 定义因数集合
        vector<int> factors = { 2, 3, 5};
        // 定义哈希表
        unordered_map<long, bool> um;
        // 定义优选队列-小顶堆
        priority_queue<long, vector<long>, greater<>> pq;
        // 放入1
        um[long(1)] = true;
        pq.push(long(1));
        long result = 0;
        for(int i = 0; i < index; ++i){
            // 每次取顶,也就是最小值,弹出
            result = pq.top();
            pq.pop();
            for(int j = 0; j < 3; ++j){
                // 存入235倍数的值
                long temp = result * factors[j];
                // 只存放非重复值
                if(um.find(temp) == um.end()){
                    um[temp] = true;
                    pq.push(temp);
                }
            }
        }
        return int(result);
    }
};

2)动态规划文章来源地址https://www.toymoban.com/news/detail-777498.html

#include <queue>
class Solution {
public:
    // 获取丑数
    int GetUglyNumber_Solution(int index) {
        // 判空
        if(index == 0){
            return 0;
        }
        // 定义丑数集合
        vector<int> uglyNums = { 1 };
        // 循环按规律找到所有丑数
        int i = 0, j = 0, k = 0;
        int t;
        for(t = 0; t < index; ++t){
            // ijk表示已知丑数乘235的进度
            // 举例说明
            // 1)开始ijk均为0,则从数字1开始,丑数后续依次为2 3 5,其中2最小,则i升为1
            // 2)i为1,即第二个丑数2,用2的2倍也就是4和3 5比较,此时3最小,则j升为1
            // 3)i和j为1,即用第二个丑数2的2倍3倍,即4和6,和5比较,此时4最小,则i继续升为2
            // 4)i为2,j为1,k为0,用3的2倍、2的3倍、1的5倍比较,即6 6 4,此时5最小,则k升为1
            // 5)i为2,j为1,k为1,用3的2倍、2的3倍,2的5倍比较,即6 6 10,此时6最小,i和j同时升1
            // 从上述5步可看到全局规律,ijk是从前往后慢慢推进的,结合了动态规划的思想,后续步进以前面为基准,动态扩展后续丑数
            int num2 = uglyNums[i] * 2;
            int num3 = uglyNums[j] * 3;
            int num5 = uglyNums[k] * 5;
            int minNum = min(num2, min(num3, num5));
            uglyNums.push_back(minNum);
            if(minNum == num2){
                i++;
            }
            if(minNum == num3){
                j++;
            }
            if(minNum == num5){
                k++;
            }
        }
        return uglyNums[t - 1];
    }
};

到了这里,关于剑指offer(C++)-JZ49:丑数(算法-其他)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 剑指offer(C++)-JZ12:矩阵中的路径(算法-回溯)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 请设计一个函数,用来判断在一个n乘m的矩阵中是否存在一条包含某长度为len的字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以

    2024年02月11日
    浏览(38)
  • 剑指offer(C++)-JZ13:机器人的运动范围(算法-回溯)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 地上有一个 rows 行和 cols 列的方格。坐标从 [0,0] 到 [rows-1,cols-1] 。一个机器人从坐标 [0,0] 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,

    2024年02月12日
    浏览(38)
  • 剑指offer(C++)-JZ63:买卖股票的最好时机(一)(算法-动态规划)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 假设你有一个数组prices,长度为n,其中prices[i]是股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益 1.你可以买入一次股票和卖出一

    2024年02月04日
    浏览(31)
  • 剑指offer(C++)-JZ64:求1+2+3+...+n(算法-位运算)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等及条件判断语句(A?B:C)。 数据范围: 0n≤200 进阶: 空间复杂度 O(1) ,时间复杂

    2024年02月09日
    浏览(34)
  • 剑指offer(C++)-JZ46:把数字翻译成字符串(算法-动态规划)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 有一种将字母编码成数字的方式:\\\'a\\\'-1, \\\'b-2\\\', ... , \\\'z-26\\\'。 现在给一串数字,返回有多少种可能的译码结果 数据范围:字符串长度满足 0n≤90 进阶:空间复杂度

    2024年02月07日
    浏览(35)
  • 剑指offer(C++)-JZ56:数组中只出现一次的两个数字(算法-位运算)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 数据范围:数组长度2≤n≤1000,数组中每个数

    2024年02月10日
    浏览(38)
  • 剑指offer(C++)-JZ48:最长不含重复字符的子字符串(算法-动态规划)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。 数据范围:  s.length≤40000 s.length≤40000 示例: 输入: 返回值: 说明

    2024年02月06日
    浏览(41)
  • 剑指offer--JZ6 从尾到头打印链表

    我写不出来,参考别人的代码后理清思路后再写的C语言版本,代码如下: 最难理解的是创建结果数组那里。我竟然不知道有这种语法。我看了老半天。malloc动态申请的内存可以看作数组使用,而且能使用数组的方式来访问元素。 大致讲解下整体思路: 1.创建一个头结点hea

    2024年02月11日
    浏览(40)
  • (其他) 剑指 Offer 67. 把字符串转换成整数 ——【Leetcode每日一题】

    难度:中等 写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可

    2024年02月09日
    浏览(38)
  • 《剑指offer》(3)排序算法篇

    class Solution:     def duplicate(self , numbers: List[int]) - int:         if len(numbers) = 1:             return -1         import collections         num_dict = collections.Counter(numbers)         res = [key for (key,value) in num_dict.items() if value 1]         return res[0] class Solution:     def sort(self,num): #快排

    2024年02月13日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包