丑数 题解

本文介绍如何解决编程题目‘丑数’,即寻找只包含质因子2、3和5的数。首先讨论了暴力求解方法及其高时间复杂度,然后提出了优化策略,通过维护一个数组和下标来降低复杂度,最后讨论了进一步的改进方案,通过记录下标避免重复遍历,提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

剑指offer 编程题:丑数。

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

基本思路(暴力解)

  • 从2开始遍历每一个数判断是不是丑数。如果是丑数计数器count++,如果不是数字加1,继续判断。算法复杂度极大。

进阶思路

  • 观察发现,每一个丑数本身必然是之前的某个丑数的值乘以2或3或5。我们只需要按照这个规律找到下一个丑数,同时确定下一个丑数是谁。简单的方式是从1开始维护一个数组,数组存放求解第N个丑数过程当中的中间结果。通过递推关系我们可以得出 :
  • next[n] = min(M2,M3,M5);
  • M2为遍历数组前n-1个元素乘以2得到的第一个大于next[n-1]的值同理可得M3,M5。
    缺陷就是每次都需要遍历前n-1个元素得到M2,M3,M5.整个算法的复杂度为O(N*N);

改进方案

其实每次在找M2,M3,M5的过程可以看成在前面的丑数当中找到某个丑数乘以2或3获刚好大于next[n-1]。
假设位置i的元素是我们需要找到求得M2的数组下标。每次从头开始到i-1遍历得到的值乘以2都会小于next[n-1],同时从i+1开始到n-1得到的乘积都大于next[n]。所以通过记录下标的方式可以不用做过多的遍历。以n2,n3,n5表示当前对于2,3,5合适的下标。初始化都为0。当求得的next[n]等于某个因子乘出来的积那么对应的下标加1。

代码

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if(index<=0) return 0;
        if(index==1) return 1;
        vector<int> v;
        v.push_back(1);
        int n2=0,n3=0,n5=0;
        for(int i=0;i<index-1;++i) {
            int m2 = v[n2]*2;
            int m3 = v[n3]*3;
            int m5 = v[n5]*5;
            int tempMin = min(m2,min(m3,m5)); //竞争产生下一个丑数 (最小)
            //将产生这个丑数的index*向后挪一位;  
            if(m2==tempMin) ++n2;
            if(m3==tempMin) ++n3;//这里不能用elseif,因为可能有两个最小值,这时都要挪动
            if(m5==tempMin) ++n5; 
            v.push_back(tempMin);
        }
        return v[index-1];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值