The Indian Engineer

Problem 786 K th Smallest Prime Fraction

Posted on 4 mins

Priority-Queue Binary-Search Array Math Heap Cpp

Problem Statement

Link - Problem 786

Question

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

Solution

class Solution {
public:
    vector<int> kthSmallestPrimeFraction(vector<int>& arr, int k) {

        std::ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);

        auto comparePair = [](const pair<int,int>& a,const pair<int,int>& b)
        {
            return a.first*b.second > b.first*a.second;
        };

        priority_queue<pair<int,int>,vector<pair<int,int>>, decltype(comparePair)>minheap;

        for(int i = 0;i<arr.size();i++)
        {
            for(int j=i+1;j<arr.size();j++)
                {
                    minheap.push(make_pair(arr[i],arr[j]));
                }
        }

        vector<int>answer(2,0);
        while(k>1 && !minheap.empty())
        {
            k--;
            minheap.pop();
        }
        answer[0] = minheap.top().first;
        answer[1] = minheap.top().second;
        return answer;
    }
};

Complexity Analysis

Explanation

1. Intuition

2. Implementation

Additional Notes

class Solution {
 public:
  vector<int> kthSmallestPrimeFraction(vector<int>& arr, int k) {
    const int n = arr.size();
    double l = 0.0;
    double r = 1.0;

    while (l < r) {
      const double m = (l + r) / 2.0;
      int fractionsNoGreaterThanM = 0;
      int p = 0;
      int q = 1;

      // For each index i, find the first index j s.t. arr[i] / arr[j] <= m,
      // so fractionsNoGreaterThanM for index i will be n - j.
      for (int i = 0, j = 1; i < n; ++i) {
        while (j < n && arr[i] > m * arr[j])
          ++j;
        if (j == n)
          break;
        fractionsNoGreaterThanM += n - j;
        if (p * arr[j] < q * arr[i]) {
          p = arr[i];
          q = arr[j];
        }
      }

      if (fractionsNoGreaterThanM == k)
        return {p, q};
      if (fractionsNoGreaterThanM > k)
        r = m;
      else
        l = m;
    }

    throw;
  }
};
Time Complexity - O(nlogn)
Space Complexity - O(1)

This problem helps us to understand how to use a min heap to solve a problem that requires finding the kth smallest element.