【剑指offer】丑数

题目描述

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

思路:因为丑数只包含 2 , 3 , 5 2,3,5 235质因子,那么我们要求第 N N N个丑数,即可以从第 1 1 1个丑数开始,接下来的一个丑数必然也只包含 2 , 3 , 5 2,3,5 235质因子,那么我们只要将第一个丑数乘以 2 , 3 , 5 2,3,5 235再取最小值即为第二个丑数,那么如何才能得到有序且无重复的丑数序列呢?

我们可以维护三个队列:
(1) 丑数数组:1
乘以2的队列:2,4,6
乘以3的队列:3,6,9
乘以5的队列:5,10,15
(2)丑数数组:1,2 (取三个队列队头的最小值)
乘以2的队列:4,6,8
乘以3的队列:3,6,9
乘以5的队列:5,10,15
(3)丑数数组:1,2,3 (取三个队列队头的最小值)
乘以2的队列:4,6,8
乘以3的队列:6,9,12
乘以5的队列:5,10,15
(4)丑数数组:1,2,3,4 (取三个队列队头的最小值)
乘以2的队列:6,8,10
乘以3的队列:6,9,12
乘以5的队列:5,10,15
(5)丑数数组:1,2 ,3,4,5 (取三个队列队头的最小值)
乘以2的队列:6,8,10
乘以3的队列:6,9,12
乘以5的队列:10,15,20

可以看到,每次都取三个队列队头的最小值进行比较,然后放入数组中,由于三个队列都是排序的,所以挑选出来的数自然也是排序的,当遇到重复的元素时,将该元素所在的队列都出队,这样就可以得到第 N N N个丑数。

实际实现:当然我们实现可以不使用队列,可以采用三个标记 t 2 、 t 3 、 t 5 t2、t3、t5 t2t3t5,当挑选了某个队列中的元素时,便将对应的标记 + + ++ ++,达到出队的效果,例如挑选了 2 2 2,则 t 2 + + t2++ t2++,那么下一次再选 2 2 2队列的元素即为 4 4 4(用 a n s [ t 2 ] ∗ 2 ans[t2] * 2 ans[t2]2表示乘以2的队列)

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
    	//丑数序列为1,2,3,4,5,6......
        if (index < 7)
            return index;
        vector<int> ans(index);
        ans[0] = 1;
        int t2 = 0, t3 = 0, t5 = 0;
        for (int i = 1; i < index; ++i) {
        	//从3个队列中选最小值
            ans[i] = min(ans[t2] * 2, min(ans[t3] * 3, ans[t5] * 5));
            //满足某一队列中的元素则出队
            if (ans[t2] * 2 == ans[i]) t2++;
            if (ans[t3] * 3 == ans[i]) t3++;
            if (ans[t5] * 5 == ans[i]) t5++;
        } 
        return ans[index - 1];
    }
};
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值