丑数

你快乐吗?

Posted by bbkgl on September 26, 2019

丑数

C++,丑数,质因数。

网上很多代码讲了怎么获得下一个最小的丑数,就是利用前面的每一个丑数分别*2*3*5,然后选出最小的那个。按照这个描述,只能每次将之前所有的丑数都和2、3、5乘一遍,那复杂度就是O(n),可网上写出来的代码都是O(n)的,你说气人不气人???

看了一会自己看懂了,把思路讲一下:

  • 首先每个丑数都是由之前的丑数乘(*2*3*5)出来的;
  • 为了得到所有丑数,我们可以从1开始,将每个丑数都乘2、3、5,然后排序,取第k个数,返回,但是这样做复杂度太大了;
  • 其实不仅每个丑数都是由之前的丑数乘出来的,而且每个丑数乘以2、3、5页必是丑数;
  • 所以,从1开始,将每个丑数分别乘以2、3、5,然后取一个最小的作为下一个丑数:
  • 为了让每个丑数都能和2、3、5相乘一次得到丑数,所以就得让得到最小丑数的那个数下次乘的丑数变成下一个,也就是让2、3、5不仅要和每个丑数相乘,而且和每个丑数只能相乘一次;
  • 所以如果让三个下标i_2、i_3、i_5分别指向下一个要和2、3、5相乘的丑数的话,假如新得到的丑数是由乘2得到,则i_2++,其他两个不用加。

代码如下:

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        vector<int> u_nums(1, 1);
        int i_2 = 0, i_3 = 0, i_5 = 0;
        while (u_nums.size() <= index) {
            int u_2 = u_nums[i_2] * 2;
            int u_3 = u_nums[i_3] * 3;
            int u_5 = u_nums[i_5] * 5;
            int min_u = min(min(u_2, u_3), u_5);
            if (min_u == u_2)
                ++i_2;
            if (min_u == u_3)
                ++i_3;
            if (min_u == u_5)
                ++i_5;
            u_nums.push_back(min_u);
        }
        return u_nums[index-1];
    }
};