丑数II

题目

Alt

思路

本题要求我们求出第n个丑数,对于某个丑数,我们最直观的感觉就是该丑数是由前面的某个丑数x2或者x3或者x5而得,所以本题的难点就在于:如何通过以前所求的丑数求某个位置的丑数
让我们首先按照动态规划的一般思路去思考:本题似乎是存在三个维度:x2的,x3的,x5的,那么如果我们设置三个dp数组,分别表示这三个维度,那么我们该如何推进状态呢,也就是说在设置这三个维度的情况下,如何求出状态转移方程呢?而且这三个维度之间也存在重叠的元素,那么这又该如何处理呢?似乎设置三个维度是增加了求状态转移方程的难度(也可能设置三个维度求不出状态转移方程)
那我们从最简单的思路入手,我们只设置一个维度,也就是只设置一个dp数组,dp[i]表示第i个位置的丑数,那么dp[i]如何从前面所求的丑数求得呢?
我们发现,某个位置的丑数是前面某个丑数x2,x3,x5(这里要注意的是,这三个乘以的丑数可能都不同)所得的最小值,也就是三个维度之间相互竞争,最小的胜出,所以状态转移方程就为:dp[i]=min(2dp[i2],3dp[i3],5*dp[i5]),总结一下具体思路就是:

  1. 设置三个指针,分别指向三个维度参与竞争的丑数
  2. 最小的胜出,同时该维度的竞争者为下一个(即后移一位指针)
  3. 依照上面的规则进行竞争,直到得出第n个丑数

相关代码如下:

class Solution {
public:
    int nthUglyNumber(int n) {
        int i2 = 0, i3 = 0, i5 = 0;
		vector<int> res(n);
		res[0] = 1;
		int i = 0;
		while (++i < n) {
			res[i] = min(min(2 * res[i2], 3 * res[i3]), 5 * res[i5]);
			if (res[i] == 2 * res[i2]) i2++;
			if (res[i] == 3 * res[i3]) i3++;
			if (res[i] == 5 * res[i5]) i5++;
		}
		return res.back();
    }
};

上述代码中值得注意的一点就是:在判断是哪个胜出的时候,使用的是三个if,这样可以解决元素重复问题

总结

本题相对于之前所做的动态规划类的题目来说,一个新颖点就是增加了指针运算,因为某个位置的丑数可能由前面的某个丑数乘2或者乘3或者乘5得来,如果我们设置三个dp数组的话,并不是很好的求解,我们抓住一个关键点就是某个位置的丑数是min(一个丑数x2,一个丑数x3,一个丑数x5),那么我们就设置三个指针,分别指向要参与竞争的三个维度对应的三个丑数,胜出的那个后移一位再参与下一轮的竞争

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值