【剑指offer】丑数

原题目:

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

解题思路:

一个丑数的因子只可能在2,3,5中,所以,一个丑数肯定由另一个丑数乘以2,3,5获得,从1开始乘得到2,3,5,再用这三个丑数乘2,3,5得到一个队列:3,6,,10,6,9,15,10,15,25,但是我们发现先这个队列有些数是重复的

所以我们可以维护三个队列,再用一个数组存储丑数:

①数组:1

乘2的队列: 2

乘3的队列: 3

乘5的队列: 5

选出三个队列头中的2加入数组,同时再把最小的乘数乘以2,3,5放入这个队列

②数组:1, 2

乘2的队列: 4

乘3的队列: 3  6

乘5的队列: 5  10

选择三个队列头最小的数3加入丑数数组

依次类推,就可以得到第k个丑数

为什么要分成三个队列呢?因为我们让一个数分别乘2,乘3,乘5,把这三种数都分别开一个队列,这样的话同一个队列中肯定有序,再每次取出最小的丑数,肯定也是有序的,而且不会又重复的数字

具体的实现思路:

不需要真的维护三个队列,分别记录三个索引,分别表示这三个队列的头在哪个位置:

①数组: 1

乘2的队列:  |2

乘3的队列:  |3

乘5的队列:  |5

②数组: 1  2

乘2的队列:  2 |4

乘3的队列:  |3 6

乘5的队列:  |5 10

③数组: 1  2  3

乘2的队列:  2 4 |6

乘3的队列:  3 |6 9

乘5的队列:  |5 10 15

具体代码如下:

int GetUglyNumber_Solution(int index) {
        if (index < 7) {
		    return index;
	    }
	    // 三个指针,分别表示2, 3, 5队列的丑数
	    int pIndex2 = 0, pIndex3 = 0, pIndex5 = 0, uglyNum = 1;
	    // 维护一个队列
	    vector<int> arr;
	    arr.push_back(uglyNum);
	    int uglyPIndexNum2, uglyPIndexNum3, uglyPIndexNum5;
	    while (arr.size() < index) {
		    // 每次选出三个队列头最小的数
		    uglyPIndexNum2 = arr[pIndex2] * 2;
		    uglyPIndexNum3 = arr[pIndex3] * 3;
		    uglyPIndexNum5 = arr[pIndex5] * 5;
		    uglyNum = min(uglyPIndexNum2, min(uglyPIndexNum3, uglyPIndexNum5));
		    arr.push_back(uglyNum);
		    if (uglyNum == uglyPIndexNum2)pIndex2++;
		    if (uglyNum == uglyPIndexNum3)pIndex3++;
		    if (uglyNum == uglyPIndexNum5)pIndex5++;
	    }
	    return uglyNum;
    }

如果遇到重复的,指针会跳过去的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值