力扣 264. 丑数 II [堆;多指针]

给你一个整数 n ,请你找出并返回第 n 个 丑数 。

丑数 就是只包含质因数 23 和/或 5 的正整数。

示例 1:

输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。

示例 2:

输入:n = 1
输出:1
解释:1 通常被视为丑数。

提示:

  • 1 <= n <= 1690

解一:小顶堆

既然要按从小到大排序,就利用小顶堆(优先队列)的性质实现自动排序:

  1. 起始先将最小丑数1放入队列
  2. 每次从队列取出最小值x,然后将x所对应的丑数2x、3x5x进行入队。
  3. 对步骤2循环多次,第n次出队的值即是答案。

为了防止同一丑数多次进队,我们需要使用数据结构Set来记录入过队列的丑数。

查看代码

class Solution {
public:
    int nthUglyNumber(int n) {
        priority_queue<long,vector<long>,greater<long>> pque;//小顶堆
        int factors[3]={2,3,5};//三个因子
        unordered_set<long> flag;//是否加入过的标志位
        flag.insert(1L);
        pque.push(1L);
        int res=0;
        for(int i=0;i<n;i++){
            long cur=pque.top();
            res=(int)cur;
            pque.pop();
            for(int j=0;j<3;j++){//依次得到cur*当前因子
                long next=factors[j]*cur;
                if(!flag.count(next)){//判断是否加入
                    flag.insert(next);
                    pque.push(next);
                }
            }
        }
        return res;
    }
};

解二:多指针

来自这里

  • 由丑数*3所得的有序序列:1*3、2*3、3*3、4*3、5*3、6*3、8*3.…
  • 由丑数*5所得的有序序列:1*5、2*5、3*5、4*5、5*5、6*5、8*5.…

举个例子,假设我们需要求得[1,2,3…,10,12]丑数序列arr的最后一位,那么该序列可以看作以下三个有序序列归并而来:

  • 1*2,2*2,3*2…,10*2,12*2,将2提出,即arr*2
  • 1*3,2*3,3*3,…,10*3,12*3,将3提出,即arr*3
  • 1*5,2*5,3*5…,10*5,12*5,将5提出,即arr*5

因此我们可以使用三个指针来指向目标序列arr的某个下标,使用arr下标*质因数代表当前使用到三个有序序列中的哪一位,同时使用idx表示当前生成到arr哪一位丑数。

查看代码
class Solution {
public:
    int nthUglyNumber(int n) {
        int res[n];//按顺序记录丑数
        res[0]=1;//下标从0开始,第一个丑数是1
        int idx2,idx3,idx5;//三个序列的下标初始为0
        idx2=idx3=idx5=0;
        for(int i=1;i<n;i++){//依次计算第i+1个丑数
            long cur2=res[idx2]*2;//如果下标生成新的丑数
            long cur3=res[idx3]*3;
            long cur5=res[idx5]*5;
            long next=min(cur2,min(cur3,cur5));//选择最小的作为第i+1个丑数
            if(cur2==next)//因为next可能不止被一个序列覆盖,所以没有else
                idx2++;
            if(cur3==next)
                idx3++;
            if(cur5==next)
                idx5++;
            res[i]=(int)next;//记录第i+1个丑数
        }
    return res[n-1];//返回第n个丑数
    }
};
posted @ 2023-01-26 20:50  付玬熙  阅读(11)  评论(0编辑  收藏  举报