Problem
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]
.
Examples
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]
Solution
Video solution here:
Method 1 - Creating all fractions and use Minheap
Code
Java
class Solution {
public int[] kthSmallestPrimeFraction(int[] arr, int k) {
PriorityQueue<Frac> minHeap = new PriorityQueue<>((a, b) -> Double.compare(a.frac, b.frac));
int n = arr.length;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
double d = (double) arr[i] / arr[j];
minHeap.add(new Frac(d, arr[i], arr[j]));
}
}
for (int i = 0; i < k - 1; i++) {
minHeap.poll();
}
Frac ans = minHeap.poll();
return new int[] { ans.nr, ans.dr };
}
class Frac {
double frac;
int nr;
int dr;
public Frac(double frac, int nr, int dr) {
this.frac = frac;
this.nr = nr;
this.dr = dr;
}
}
}
Complexity
- ⏰ Time complexity:
O(N^2 logn)
- 🧺 Space complexity:
O(n^2)
Method 2 - Using provided sorted array efficiently and minHeap 🏆
The optimized method aims to leverage the point that array is sorted. So, we can find the k-th smallest fraction from all possible pairs in a sorted array without generating all combinations upfront.
Algorithm
- Initialize minHeap based on the fractional value. We don’t have. to double compare. Let nr represents numerator and dr represents denominator, this implies if
nr0/dr0 > nr1/dr1
⇨nr0*dr1 > nr1 * dr0
- Push all the smallest possible fraction by pushing all numerator with array’s largest value as denominator to the minHeap.
- Extract the smallest fraction from minHeap, and replace it with the next fraction by using same numerator, but just smaller denominator
- Continue this step 3, till we have extracted
k
elements, and kth’ element is our answer
- Continue this step 3, till we have extracted
Dry Run
- We create
minHeap
- We push all pairs as
{nrIdx, drIdx}
⇨ numerator and denominator index - We push all numerators from0
ton-2
and last indexn-1
as denominators - Now, we poll each pair one by one. We poll out numerator and denominator pair. If the we have reached
k
, we return current answer- and if we have not reached k, we push new
{nrIdex, drIdx - 1}
providednrIdx != (drIdx - 1)
.
- and if we have not reached k, we push new
Code
Java
public int[] kthSmallestPrimeFraction(int[] arr, int k) {
PriorityQueue<int[]> minHeap = new PriorityQueue<>(
(a, b) -> Integer.compare(arr[a[0]] * arr[b[1]], arr[a[1]] * arr[b[0]]));
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
minHeap.add(new int[] { i, n - 1 });
}
for (int i = 0; i < k - 1; i++) {
int[] frac = minHeap.poll();
int nrIdx = frac[0];
int drIdx = frac[1];
if (drIdx - 1 > nrIdx) {
minHeap.add(new int[] { nrIdx, drIdx - 1 });
}
}
int[] ans = minHeap.poll();
int nrIdx = ans[0];
int drIdx = ans[1];
return new int[] { arr[nrIdx], arr[drIdx] };
}
Complexity
- ⏰ Time complexity:
O(n log n)
as it takesO(n)
to build minHeap andO(k log n)
to pick firstk
elements from heap. - 🧺 Space complexity:
O(n)