标签:
Write a program to find the n-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.
Note that 1 is typically treated as an ugly number.
Hint:
isUgly for every number until you reach the nth one. Most numbers are not ugly. Try to focus your effort on generating only the ugly ones.Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
解法1:从2到n循环,对每个数进行isUgly判断,会超时Time Limit Exceeded
class Solution { public: int nthUglyNumber(int n) { int num = 2; while(n > 1) { if(isUgly(num)) --n; ++num; } return --num; } private: bool isUgly(int num) { while(num > 0 && num % 2 == 0) num /= 2; while(num > 0 && num % 3 == 0) num /= 3; while(num > 0 && num % 5 == 0) num /= 5; return num == 1; } };
解法2:根据提供的Hint,我们知道丑陋数序列可以拆分为下面3个子列表:
(2) 1×2, 2×2, 3×2, 4×2, 5×2, …
(3) 1×3, 2×3, 3×3, 4×3, 5×3, …
(5) 1×5, 2×5, 3×5, 4×5, 5×5, …
一个新的丑数可以看做是一个旧的丑数乘以2,3,5得到的(第一个丑数是1,第二个为2,则第二个可以看做第一个丑数*2得到了第二个丑数(1*2、1*3和1*5中的最小者)),本题解题难点在于维护丑数数列为从小到大排列的顺序。
根据上述思路可以做如下实现:
class Solution { public: int nthUglyNumber(int n) { int count = 1; int num = 1; list<int> l2; list<int> l3; list<int> l5; while(count != n) { l2.push_back(2*num); l3.push_back(3*num); l5.push_back(5*num); int l2min = l2.front(); int l3min = l3.front(); int l5min = l5.front(); int minNum = min(l2min, min(l3min, l5min)); if(l2min == minNum) l2.pop_front(); if(l3min == minNum) l3.pop_front(); if(l5min == minNum) l5.pop_front(); num = minNum; ++count; } return num; } };
改进:对于乘以2而言,肯定存在某一个丑数t2,使得排在它之前的每一个丑数乘以2得到的结果都会小于已有最大丑数,在它之后的每个丑数乘以2得到的结果都会大于当前最大丑数。我们只需要记下这个丑数的位置,同时每次生成新的丑数时去更新这个t2。对于3和5,同样存在t3和t5。
class Solution { public: int nthUglyNumber(int n) { vector<int> uglyNumSeq(1, 1); int i2 = 0, i3 = 0, i5 = 0; while (uglyNumSeq.size() < n) { int n2 = uglyNumSeq[i2] * 2; int n3 = uglyNumSeq[i3] * 3; int n5 = uglyNumSeq[i5] * 5; int next = min(n2, min(n3, n5)); if (next == n2) ++i2; if (next == n3) ++i3; //注意不用else if,因为不同序列可能有相同值 if (next == n5) ++i5; uglyNumSeq.push_back(next); } return uglyNumSeq.back(); } };
[LeetCode]70. Ugly Number II第N个丑数
标签:
原文地址:http://www.cnblogs.com/aprilcheny/p/4950442.html