丑数

题目

  把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数

思路

,假设这个数为 n, 如果n是丑数,只有三种可能:

  1. n是能整除2,即 n % 2 == 0,且 n/2 是丑数。
  2. n % 3 == 0 且 n/3是丑数。
  3. n % 5 == 0且 n / 5是丑数。

三种可能只要满足其中一种,就可以确认是丑数了。

二 ,为了优化内存,只能想办法不存储所有的数了,而是用一个集合存储所有的丑数,如果要求第n个丑数,也就最多使用n个存储空间。而判断一个数是不是丑数的方法就是判断该数在不在这个集合中。

  可用unordered_set容器来存储“丑数”,先判断这个数是否在容器中,若是不在,并且该数是个“丑数”,就添加到容器中。

三,如果已知了n个丑数,第n+1个丑数必然是前面的某个丑数乘以2,或者乘以3,或者乘以5。至于是谁,就是都尝试一下,取最小。

现在已知6个丑数 1 2 3 4 5 6, 求第7个丑数。

可以翻译成:假设dp[i]表示第i个丑数的数值,已知丑数的个数为count=6,且前6个丑数 dp[1]=1;dp[2]=2;dp[3]=3;dp[4]=4;dp[5]=5;dp[6]=6; 求dp[7]

dp[7]可能有三种情况:

  • i=1开始按顺序求v = dp[i]*2,当v>dp[6],可以停止,则第4个丑数乘2得到的8可能是第7个丑数。
  • i=1开始按顺序求v = dp[i]*3,当v>dp[6],可以停止,则第3个丑数乘3得到的9可能是第7个丑数。
  • i=1开始按顺序求v = dp[i]*5,当v>dp[6],可以停止,则第3个丑数乘5得到的10可能是第7个丑数。

取三种情况的最小值,得到8,就是第7个丑数,即dp[7] = 8

依此类推,可以求得第8个丑数。

有个小优化按顺序搜索的时候并不需要每次都从1开始,只需要从上次搜索的结束点继续搜索就行了

例如求dp[8],同样有三种情况:

  • i=4开始按顺序求v = dp[i]*2,当v>dp[7],可以停止,则第5个丑数乘2得到的10可能是第8个丑数。
  • i=3开始按顺序求v = dp[i]*3,当v>dp[7],可以停止,则第3个丑数乘3得到的9可能是第8个丑数。
  • i=2开始按顺序求v = dp[i]*5,当v>dp[7],可以停止,则第2个丑数乘5得到的10可能是第8个丑数。

取三种情况的最小值,得到10,即dp[8] = 9

class Solution {
public:
    int nthUglyNumber(int n) {
        if (n <= 6) {
            return n;
        }

        vector<int> arr(n + 1);
        for (int i = 1; i <= 6; ++i) {
            arr[i] = i;
        }

        int index = 6;
        int start1 = 1, start2 = 1, start3 = 1;
        while (index < n) {
            for (int i = start1; i <= index; ++i) {
                if (arr[i] * 2 > arr[index]) {
                    start1 = i;
                    break;
                }
            }

            for (int i = start2; i <= index; ++i) {
                if (arr[i] * 3 > arr[index]) {
                    start2 = i;
                    break;
                }
            }

            for (int i = start3; i <= index; ++i) {
                if (arr[i] * 5 > arr[index]) {
                    start3 = i;
                    break;
                }
            }
            arr[++index] = min(min(arr[start1] * 2, arr[start2] * 3), arr[start3] * 5);
        }
        return arr[index];
    }
};

 

posted on 2019-01-12 13:44  tianzeng  阅读(237)  评论(0编辑  收藏  举报

导航