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.
最简单的想法是:从1开始逐个数判断是否是丑数,如果是计数器加1,直到找到第K个丑数;这种方式会判断大量的非丑数,耗时太大。
更直接的想法:直接找丑数:第一个丑数为1,找到第二个比1大的丑数为2,第三个比2的丑数为3,第三个比3的丑数为4.....通过一定的法则,每次计算出下一个最小的丑数。只需要计算K次,耗时大量减少。
假设数组UglyNumbers中已经有了M个丑数,把已有的每个丑数都分别乘以2,3,5。然后从中找到最小的比UglyNumbers[M-1]大的数即为下一个丑数。然而这其中仍有有很多不必要的计算。事实上,对乘以2而言,肯定存在某一个丑数T2,排在它前面的每一个丑数乘以2得到的结果都会小于已有最大的丑数UglyNumbers[M-1];排在它之后的每一个丑数乘以2得到的结果都会太大。我们只需记下这个丑数的位置,同时每次生成新的丑数的时候,去更新这个T2。对乘以3和乘以5而言,也存在着同样的问题。
<pre name="code" class="cpp">
class Solution { public: int nthUglyNumber(int n) { if(n<=0) return 0; int *UglyNumbers=new int[n];//存储前n个找到的uglynumber,每次找一个最小的uglynumber UglyNumbers[0]=1; int *pMutiply2 = UglyNumbers; int *pMutiply3 = UglyNumbers; int *pMutiply5 = UglyNumbers; int i = 1; while(i<n){ int NextUglyNumber = Min(*pMutiply2*2,*pMutiply3*3,*pMutiply5*5); UglyNumbers[i]= NextUglyNumber; while(*pMutiply2*2<=NextUglyNumber) ++pMutiply2; while(*pMutiply3*3<=NextUglyNumber) ++pMutiply3; while(*pMutiply5*5<=NextUglyNumber) ++pMutiply5; ++i; } int ans = UglyNumbers[n-1]; delete[] UglyNumbers; return ans; } int Min(int a,int b,int c){ return (a<=b && a<=c)?a:((b<=c?b:c)); } };