标签: 堆(优先队列)

LeetCode刷题【剑指 Offer 49】丑数

我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

 

示例:

输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。

说明:  

  1. 1 是丑数。
  2. n 不超过1690。

注意:本题与主站 264 题相同:https://leetcode-cn.com/problems/ugly-number-ii/

Related Topics
  • 哈希表
  • 数学
  • 动态规划
  • 堆(优先队列)

  • 👍 356
  • 👎 0
  • dp,算是dp吧

    解题思路

    此处撰写解题思路

    代码

    class Solution {
        public int nthUglyNumber(int n) {
            int[] dp = new int[n];
            dp[0] = 1;
            int[] numArr = new int[]{2,3,5};
            int[] pArr = new int[3];
            for (int i = 1; i < n; i++) {
                dp[i] = Math.min(Math.min(dp[pArr[0]]*numArr[0],dp[pArr[1]]*numArr[1]),dp[pArr[2]]*numArr[2]);
                for (int p = 0; p < pArr.length; p++) {
                    if (dp[i] == dp[pArr[p]]*numArr[p]){
                        pArr[p]++;
                    }
                }
            }
            return dp[n-1];
        }
    }

    LeetCode刷题【面试题40】最小的k个数

    输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

     

    示例 1:

    输入:arr = [3,2,1], k = 2
    输出:[1,2] 或者 [2,1]
    

    示例 2:

    输入:arr = [0,1,2,1], k = 1
    输出:[0]

     

    限制:

    • 0 <= k <= arr.length <= 10000
    • 0 <= arr[i] <= 10000
    Related Topics
    • 数组
    • 分治
    • 快速选择
    • 排序
    • 堆(优先队列)

  • 👍 450
  • 👎 0
  • 堆排序

    解题思路

    此处撰写解题思路

    代码

    class Solution {
        public int[] getLeastNumbers(int[] arr, int k) {
            if (k == 0){
                return new int[0];
            }
            PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2 - o1;
                }
            });
            for (int i : arr) {
                if (queue.size() < k){
                    queue.offer(i);
                }else if(i < queue.peek()){
                    queue.poll();
                    queue.offer(i);
                }
            }
            int[] res = new int[k];
            for (int i = 0; i < res.length; i++) {
                res[i] = queue.poll();
            }
            return res;
        }
    }

    LeetCode刷题【506】相对名次

    给你一个长度为 n 的整数数组 score ,其中 score[i] 是第 i 位运动员在比赛中的得分。所有得分都 互不相同

    运动员将根据得分 决定名次 ,其中名次第 1 的运动员得分最高,名次第 2 的运动员得分第 2 高,依此类推。运动员的名次决定了他们的获奖情况:

    • 名次第 1 的运动员获金牌 "Gold Medal"
    • 名次第 2 的运动员获银牌 "Silver Medal"
    • 名次第 3 的运动员获铜牌 "Bronze Medal"
    • 从名次第 4 到第 n 的运动员,只能获得他们的名次编号(即,名次第 x 的运动员获得编号 "x")。

    使用长度为 n 的数组 answer 返回获奖,其中 answer[i] 是第 i 位运动员的获奖情况。

     

    示例 1:

    输入:score = [5,4,3,2,1]
    输出:["Gold Medal","Silver Medal","Bronze Medal","4","5"]
    解释:名次为 [1st, 2nd, 3rd, 4th, 5th] 。

    示例 2:

    输入:score = [10,3,8,9,4]
    输出:["Gold Medal","5","Bronze Medal","Silver Medal","4"]
    解释:名次为 [1st, 5th, 3rd, 2nd, 4th] 。
    

     

    提示:

    • n == score.length
    • 1 <= n <= 104
    • 0 <= score[i] <= 106
    • score 中的所有值 互不相同
    Related Topics
    • 数组
    • 排序
    • 堆(优先队列)

     

    • 👍 180
    • 👎 0

    优先队列

    解题思路

    此处撰写解题思路

    代码

    class Solution {
        public String[] findRelativeRanks(int[] score) {
            PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
                @Override
                public int compare(int[] o1, int[] o2) {
                    return o2[0] - o1[0];
                }
            });
            for (int i = 0; i < score.length; i++) {
                queue.add(new int[]{score[i],i});
            }
            String[] arr = new String[score.length];
            String[] top = new String[]{"Gold Medal","Silver Medal","Bronze Medal"};
            int i = -1;
            while (!queue.isEmpty()){
                int[] cur = queue.poll();
                if (++i < top.length){
                    arr[cur[1]] = top[i];
                }else{
                    arr[cur[1]] = (i + 1) + "";
                }
            }
            return arr;
        }
    }

    LeetCode刷题【786】第 K 个最小的素数分数

    给你一个按递增顺序排序的数组 arr 和一个整数 k 。数组 arr1 和若干 素数  组成,且其中所有整数互不相同。

    对于每对满足 0 <= i < j < arr.lengthij ,可以得到分数 arr[i] / arr[j]

    那么第 k 个最小的分数是多少呢?  以长度为 2 的整数数组返回你的答案, 这里 answer[0] == arr[i] 且 answer[1] == arr[j]

     

    示例 1:

    输入:arr = [1,2,3,5], k = 3
    输出:[2,5]
    解释:已构造好的分数,排序后如下所示: 
    1/5, 1/3, 2/5, 1/2, 3/5, 2/3
    很明显第三个最小的分数是 2/5
    

    示例 2:

    输入:arr = [1,7], k = 1
    输出:[1,7]
    

     

    提示:

    • 2 <= arr.length <= 1000
    • 1 <= arr[i] <= 3 * 104
    • arr[0] == 1
    • arr[i] 是一个 素数i > 0
    • arr 中的所有数字 互不相同 ,且按 严格递增 排序
    • 1 <= k <= arr.length * (arr.length - 1) / 2
    Related Topics
    • 数组
    • 二分查找
    • 排序
    • 堆(优先队列)

  • 👍 221
  • 👎 0
  • 优先队列两种实现

    首先,直接上来一个优先队列,自定义排序。

    为了实现这个自定义的排序,我们需要记录几个东西

    1. 分子
    2. 分母
    3. 为了便于比较,相除后的小数值也可以事先计算好,比较的时候就直接比较这个数字即可
    4. 把所有的都放进去之后,我们就开始从头部取出K个即可
    5. 最终得到第K个的分子分母即可

    理解起来也相对比较简单

    代码

    class Solution {
        public int[] kthSmallestPrimeFraction(int[] arr, int k) {
            PriorityQueue<double[]> queue = new PriorityQueue<>(new Comparator<double[]>() {
                @Override
                public int compare(double[] o1, double[] o2) {
                    if (o1[2] >= o2[2]){
                        return 1;
                    }
                    return -1;
                }
            });
            for (int i : arr) {
                for (int j : arr) {
                    queue.offer(new double[]{(double)i,(double)j,((double)i)/j});
                }
            }
            while (--k > 0){
                queue.poll();
            }
            return new int[]{(int)queue.peek()[0],(int)queue.peek()[1]};
        }
    }

    写完这个之后思考一下,我们真的需要把所有的值都算一遍全都存进优先队列么?答案是否定的,

    1. 我们可以把数据分别按照分母分成arr[]数组长度个分组,
    2. 分别维护一个指针,指向当前对应的分子,
    3. 这样我们的优先队列只要维护比较arr[]数组长度个值即可,每当从队列头部取出一个对象时,只需把分子位置往后挪动一位,重新放入队列
    4. 如果分子指针位置已经到达了arr[]数组尾部,则不再需要往队列中添加

    代码

    class Solution {
        public int[] kthSmallestPrimeFraction(int[] arr, int k) {
            PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
                @Override
                public int compare(int[] o1, int[] o2) {
                    if (((double)arr[o1[0]])/arr[o1[1]] >= ((double)arr[o2[0]])/arr[o2[1]]){
                        return 1;
                    }
                    return -1;
                }
            });
            for (int i = 0; i < arr.length; i++) {
                queue.offer(new int[]{0,i});
            }
            while (--k > 0) {
                int[] top = queue.poll();
                if (top[0] < arr.length){
                    top[0]++;
                    queue.offer(top);
                }
            }
            return new int[]{arr[queue.peek()[0]],arr[queue.peek()[1]]};
        }
    
    }