剑指offer刷题

丑数(空间换时间)

2019-06-22  本文已影响0人  侯俊同学

根据丑数的定义, 丑数应该是另一个丑数乘以 2、3 或者 5 的结果(1 除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数,每一个丑数都是前面的丑数乘以 2、3 或者 5 得到的。

这种思路的关键在于怎样确保数组里面的丑数是排好序的。假设数组中已经有若干个丑数排好序后存放在数组中,并且把己有最大的丑数记做M,我们接下来分析如何生成下一个丑数。该丑数肯定是前面某一个丑数乘以 2、3 或者 5 的结果, 所以我们首先考虑把已有的每个丑数乘以 2。在乘以 2 的时钝能得到若干个小于或等于 M 的结果。由于是按照顺序生成的,小于或者等于 M 肯定己经在数组中了,我们不需再次考虑:还会得到若干个大于 M 的结果,但我们只需要第一个大于 M 的结果,因为我们希望丑数是按从小到大的顺序生成的,其他更大的结果以后再说。我们把得到的第一个乘以 2 后大于 M 的结果记为 M2,同样,我们把已有的每一个丑数乘以 3 和 5,能得到第一个大于 M 的结果 M3 和 M,那么下一个丑数应该是 M2、M3 和 M5 这 3 个数的最小者。

前面分析的时候,提到把已有的每个丑数分别都乘以 2、3 和 5。事实上这不是必须的,因为已有的丑数是按顺序存放在数组中的。对乘以 2 而言, 肯定存在某一个丑数 T2,排在它之前的每一个丑数乘以 2 得到的结果都会小于已有最大的丑数,在它之后的每一个丑数乘以 2 得到的结果都会太大。我们只需记下这个丑数的位置, 同时每次生成新的丑数的时候,去更新这个 T2。对乘以 3 和 5 而言, 也存在着同样的 T3 和 T5。

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if(index<7)
            return index;
        vector<int> ugly(index);
        for(int i = 0;i<6;++i)
            ugly[i]=i+1;
        
        int t2=3,t3=2,t5=1;
        for(int i=6;i<index;++i)
        {
            //取t2,t3,t5最小的那个
            ugly[i]  = min(ugly[t2] * 2, min(ugly[t3] * 3, ugly[t5] * 5));
            //更新t2,t3,t5
            while(ugly[t2]*2<=ugly[i]) t2++;
            while(ugly[t3]*3<=ugly[i]) t3++;
            while(ugly[t5]*5<=ugly[i]) t5++;
        }
        return ugly[index-1];
    }
};
上一篇下一篇

猜你喜欢

热点阅读