Ugly Number II

来源:互联网 发布:淘宝库房分拣员累吗 编辑:程序博客网 时间:2024/06/14 01:40

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:

Show Hint
  1. The naive approach is to callisUgly for every number until you reach the nth one. Most numbers arenot ugly. Try to focus your effort on generating only the ugly ones.Show More Hint
  2. An ugly number must be multiplied by either 2, 3, or 5 from a smaller ugly number.Show More Hint
  3. The key is how to maintain the order of the ugly numbers. Try a similar approach of merging from three sorted lists: L1, L2, and L3.Show More Hint
  4. Assume you have Uk, the kth ugly number. Then Uk+1 must be Min(L1 * 2, L2 * 3, L3 * 5).

题目定义了一种数叫做ugly number,由2、3、5三个数字任意相乘得到的数就是ugly number。题目要求我们找到从1开始的第n个ugly number。

对于这个题目,我在看到提示之前我没有想到系统的方法来构建ugly number,我能想到的办法就是从大到小一个个去试,经过我的尝试,这样暴力求解果然是会超时的。

看到了提示以后,我们就可以按照提示的方法来做,我们先构建3个队列,而每次找新的ugly number的方法是取三个队列中的头元素(它们肯定是各自队列中的最小数)分别乘以2、3、5,然后再在结果中取最小的数,产生的这个ugly number有可能是前面已经产生过的,所以要与已经在队列中的元素比较,如果比已经在队列中的元素大,那么它是新的ugly number,把它放进3个队列中。我用一个变量来记录已经产生ugly number的个数,达到题目要求的个数就停止。

因为1是最小的ugly number,所以在最开始的时候需要把1放进3个队列中。

这个算法对于每个ugly number都需要和3个不同的数相乘来构造新的ugly number,所以while循环的次数约为3n,所以时间复杂度为O(n),以下为源代码:

class Solution {public:    int nthUglyNumber(int n) {        int index=1,num=1;        queue<int> l1,l2,l3;        l1.push(1);        l2.push(1);        l3.push(1);        while(index<n)        {            int t1=l1.front()*2;            int t2=l2.front()*3;            int t3=l3.front()*5;            if(t1<=t2&&t1<=t3)            {                num=t1;                l1.pop();            }            else if(t2<=t1&&t2<=t3)            {                num=t2;                l2.pop();            }            else            {                num=t3;                l3.pop();            }            if((l1.empty()||num>l1.back())&&(l2.empty()||num>l2.back())&&(l3.empty()||num>l3.back()))            {            l1.push(num);            l2.push(num);            l3.push(num);            index++;            }        }        return num;    }};

0 0