星星博客 »  > 

Leetcode 786:第 K 个最小的素数分数 K-th Smallest Prime Fraction

中文描述:

给你一个按递增顺序排序的数组 arr 和一个整数 k 。数组 arr 由 1 和若干 素数组成,且其中所有整数互不相同。
对于每对满足 0 < i < j < arr.length 的 i 和 j ,可以得到分数 arr[i] / arr[j] 。
那么第 k 个最小的分数是多少呢? 以长度为 2 的整数数组返回你的答案, 这里 answer[0] == arr[i] 且 answer[1] == arr[j] 。

题目描述:

You are given a sorted integer array arr containing 1 and prime numbers, where all the integers of arr are unique. You are also given an integer k.
For every i and j where 0 <= i < j < arr.length, we consider the fraction arr[i] / arr[j].
Return the kth smallest fraction considered. Return your answer as an array of integers of size 2, where answer[0] == arr[i] and answer[1] == arr[j].

Example 1:

Input: arr = [1,2,3,5], k = 3
Output: [2,5]
Explanation: The fractions to be considered in sorted order are:
1/5, 1/3, 2/5, 1/2, 3/5, and 2/3.
The third fraction is 2/5.

Example 2:

Input: arr = [1,7], k = 1
Output: [1,7]

Constraints:

2 <= arr.length <= 1000
1 <= arr[i] <= 3 * 104
arr[0] == 1
arr[i] is a prime number for i > 0.
All the numbers of arr are unique and sorted in strictly increasing order.
1 <= k <= arr.length * (arr.length - 1) / 2

方法1:
Time complexity: O ( K l o g N ) O(KlogN) O(KlogN), N:数组的长度. heap 最多有N个元素,当pop元素是 需要 花费 O ( l o g N ) O(logN) O(logN) . 需要O(K)次pop.
Space complexity: O ( N ) O(N) O(N) Heap size
优先队列/堆:
以example 以为例子,所有构成的分数结果可以看成是一个二维的矩阵
1/1 2/1 3/1 5/1
1/2 2/2 3/2 5/2
1/3 2/3 3/3 5/3
1/5 2/5 3/5 5/5

  1. 我们建一个最小堆,堆定元素是最小值。根据题目根据 分子answer[0]/分母answer[1] 来排序。
  2. 我们把矩阵的最左边一列加到堆中,以为数组是拍过序的所以 arr[0]/arr[arr.length-1] 一定是最小值在堆顶。考虑到限定条件:0 < i < j < arr.length 的 i 和 j。1/1 不用加加到堆中。
  3. 根据矩阵第2小的可能是 往上 1/3 减小分母 或者往右 2/5 增加分子.
  4. 因为开始我们已经把 1/3 加到了堆中,所以此时只需要把 2/5 放到堆中就行。
  5. 最后 在k-1次pop 之后此时堆顶的元素就是 第k小的元素。
class Solution {
    //  1   2   3   4    5
    //  1/5 1/4 1/3 1/2
    //  2/5 2/4 2/3 
    //  1/2 
    //  2/3 
    // a[0]/a[1] < arr[]
    public int[] kthSmallestPrimeFraction(int[] arr, int k) {
        PriorityQueue<int[]> pq = new PriorityQueue<int[]>((a,b)->arr[a[0]]*arr[b[1]] - arr[a[1]]*arr[b[0]]);
        int n = arr.length;
        
        for(int i = 1; i < n; i++){
            pq.add(new int[]{0, i});
        }
        
        while(k > 1){
            int[] frac = pq.poll();
            if(frac[0]++ < frac[1]){
               pq.add(frac); 
            }
            k--;
        }
        
        int[] ans = pq.poll();
        return new int[]{arr[ans[0]], arr[ans[1]]};
    }
}

相关文章