LeetCode264:丑数II

编写一个程序,找出第 n 个丑数。

丑数就是只包含质因数 2, 3, 5 的正整数。

剑指OFFER上也有这道题。

思路:

  对于某一个丑数来说,它一定是它前面的某个丑数乘以2或3或5得到的,我们要选取 所得到的 所有丑数中最小的一个作为这个位置的新丑数,比如1 2 3 4 5后,6,8,9都是丑数,但要选取6。

一开始的思路是保存前面得到的丑数,然后分别对他们x2,x3,x5,最后从大于i-1位置的丑数中最小的。

这个方法的问题在于多了很多重复计算,比如1x2,1x3,1x5是没必要计算的。

因此:

对某个数来说,它一定是某个位置X2,或另一位置的丑数X3,或另一位置的丑数X5得到的,因此我们使用三个指针p2,p3,p5,p2指向的丑数专门用于X2,p3指向的丑数专门用于X3,p5指向的丑数专门用于X5。这里可能有个疑问,为什么p2指向的位置只能X2不能X3或X5呢,因为p3也是可能指向这个数的,X3我们交由p3去做就好了。

用三个位置的指针相乘得到的最小结果就作为i位置的丑数,得到这个丑数后还要更新p2,p3,p5。这是为了节省计算量,假设现在p2指向的数乘以2作为新位置的丑数,下一次计算新的丑数时,这个p2指向的位置就没必要计算了,因为它乘以2后得到的是i位置的丑数,一定小于i+1位置的丑数,因此我们要更新p2的位置;同时也要与num[p3]*3和num[p5]*5作对比,以6为例,3x2可以得到6,但2x3也可以得到6,因此还要与p3和p5的结果做比较,如果相等则同步也要更新p3与p5的指向。

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
		vector<int> ans(index);
		ans[0]=1;
		int p2=0,p3=0,p5=0;
		for(int i=1;i<index;i++)
		{
			ans[i]=min(ans[p2]*2,min(ans[p3]*3,ans[p5]*5));
			if(ans[i]==ans[p2]*2)
				p2++;
			if(ans[i]==ans[p3]*3)
				p3++;
			if(ans[i]==ans[p5]*5)
				p5++;
		}
		return ans.back();
	}
};

  

原文地址:https://www.cnblogs.com/lxy-xf/p/11386943.html