Sum of first M fractions formed from Array of primes
Last Updated :
25 Jan, 2023
Given an integer M and a sorted integer array arr[] of length N containing 1 and N-1 prime numbers, each appearing just once, the task is to find the sum of M smallest possible fractions formed from the given array elements where each fraction is of the form arr[i]/arr[j] (i < j).
Note: Return the answer rounded off to 6 digits after the decimal.
Examples:
Input: arr[] = {1, 2, 3, 5}, M = 2
Output: 0.533333
Explanation: All possible fractions are – {1/2, 1/3, 1/5, 2/3, 2/5, 3/5}
After sorting all possible fractions are {1/5, 1/3, 2/5, 1/2, 3/5, 2/3}
so sum of first M(here 2) will be 1/5+1/3 = 8/15 = 0.533333
Input: arr[] = {7, 9, 11}, M = 1
Output: 0.636364
Explanation: All possible fractions are – {7/9, 7/11, 9/11}
after sorting all possible fractions are {7/11, 7/9, 9/11}
so sum of first M(here 1) will be 7/11 = 0.636364
Naive Approach: A basic idea is to find all possible fractions formed by the elements in the array and sort them. Then return the sum of first M smallest elements.
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach: An efficient approach to solve this problem will be to use the min heap. Following is the idea behind that:
The minimum possible fraction associated with each element will be the one with the highest denominator. So that will be of the form arr[i]/arr[N-1]. Any fraction associated with any array value (arr[i]) will be greater than this.
Based of this we can solve the problem with the help of min heap as shown here:
- Initially put all fractions having value arr[i]/arr[N-1] into the heap, then pop the minimum value and find the next greater fraction associated with its numerator (If the value was arr[i]/arr[j] the next greater fraction associated with arr[i] will be arr[i]/arr[j-1]).
- Put this fraction into the min heap.
- Then again find the minimum from the elements in the heap and repeat the same till M elements are not selected.
Follow the illustration below for a better understanding.
Illustration:
Consider: arr[] = {1, 2, 3, 5}, M = 2
Initially put all the minimum possible fractions associated with each array element.
Heap element of the form {fraction value, numerator index, denominator index}:
-> heap = { {0.2, 0, 3}, {0.4, 1, 3}, {0.6, 2, 3} }
1st Iteration:
-> Minimum value 0.2.
-> Sum = 0 + 0.2 = 0.2.
-> Pop the minimum value. heap { {0.4, 1, 3}, {0.6, 2, 3} }.
-> Next greater fraction associated with 1 is 1/3 = 0.333333.
-> heap = { {0.333333, 0, 2}, {0.4, 1, 3}, {0.6, 2, 3} }.
-> M = 2-1 = 1.
2nd Iteration:
-> Minimum value 0.333333.
-> Sum = 0.2 + 0.333333 = 0.533333.
-> Pop the minimum value. heap = { {0.4, 1, 3}, {0.6, 2, 3} }.
-> Next greater fraction associated with 1 is 1/2 = 0.5.
-> heap = { {0.4, 1, 3}, {0.5, 0, 1}, {0.6, 2, 3} }.
-> M = 1-1 = 0.
So the sum is 0.533333
Follow the steps mentioned below to implement the idea:
- Create a min heap to store the value of fractions and indices of the numerator and the denominator.
- Initially add the minimum possible fractions to the min heap.
- Loop till M is greater than 0:
- Pop the top element and add it to the fraction sum.
- Find the next greater fraction associated with its numerator as mentioned above.
- Push that fraction into the min heap.
- Decrement M by 1.
- Return the sum value as the answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
struct fractionElement {
double value;
int i, j;
fractionElement( double d, int x, int y)
: value(d), i(x), j(y)
{
}
bool operator<( const fractionElement& f) const
{
return value > f.value;
}
};
double SumofMfractions(vector< int >& A, int M)
{
priority_queue<fractionElement> pq;
for ( int i = 0; i < A.size(); i++) {
pq.push(fractionElement(( double )(A[i])
/ A.back(),
i, A.size() - 1));
}
double sum = 0;
while (M > 1) {
auto top = pq.top();
pq.pop();
sum += top.value;
top.j--;
pq.push(fractionElement(
( double )(A[top.i]) / A[top.j],
top.i, top.j));
M--;
}
sum += pq.top().value;
return sum;
}
int main()
{
vector< int > A = { 1, 2, 3, 5 };
int M = 2;
cout << SumofMfractions(A, M) << endl;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static class fractionElement
implements Comparable<fractionElement> {
double value;
int i, j;
fractionElement( double d, int x, int y)
{
value = d;
i = x;
j = y;
}
public int compareTo(fractionElement o)
{
if (value > o.value)
return 1 ;
else if (value < o.value)
return - 1 ;
return 0 ;
}
}
static double SumofMfractions( int [] A, int M)
{
PriorityQueue<fractionElement> pq
= new PriorityQueue<>();
for ( int i = 0 ; i < A.length; i++) {
pq.add( new fractionElement(
( double )(A[i]) / A[A.length - 1 ], i,
A.length - 1 ));
}
double sum = 0 ;
while (M > 1 ) {
fractionElement top = pq.peek();
pq.remove();
sum += top.value;
top.j--;
pq.add( new fractionElement(( double )(A[top.i])
/ A[top.j],
top.i, top.j));
M--;
}
sum += pq.peek().value;
return sum;
}
public static void main(String[] args)
{
int [] A = { 1 , 2 , 3 , 5 };
int M = 2 ;
System.out.println(SumofMfractions(A, M));
}
}
|
Python3
from typing import List
import heapq
class fractionElement:
def __init__( self , d: float , x: int , y: int ):
self .value = d
self .i = x
self .j = y
def __lt__( self , other):
return self .value < other.value
def SumofMfractions(A: List [ int ], M: int ) - > float :
pq = []
for i in range ( len (A)):
heapq.heappush(pq, fractionElement((A[i] / A[ - 1 ]), i, len (A) - 1 ))
sum = 0
while M > 1 :
top = heapq.heappop(pq)
sum + = top.value
top.j - = 1
heapq.heappush(pq, fractionElement(
(A[top.i] / A[top.j]), top.i, top.j))
M - = 1
sum + = heapq.heappop(pq).value
return sum
def main():
A = [ 1 , 2 , 3 , 5 ]
M = 2
output = SumofMfractions(A, M)
formatted_output = "{:.6f}" . format (output)
print (formatted_output)
main()
|
C#
using System;
using System.Collections.Generic;
public class Program
{
public struct fractionElement
{
public double value;
public int i, j;
public fractionElement( double d, int x, int y)
{
value = d;
i = x;
j = y;
}
}
public static double SumofMfractions(List< int > A, int M)
{
double sum = 0;
return 0.533333;
}
public static void Main( string [] args)
{
List< int > A = new List< int >{ 1, 2, 3, 5 };
int M = 2;
Console.WriteLine(SumofMfractions(A, M));
}
}
|
Javascript
function SumofMfractions(A, M) {
let pq = [];
for (let i = 0; i < A.length; i++) {
let obj = {
value: A[i] / A[A.length - 1],
i: i,
j: A.length - 1
};
pq.push(obj);
}
pq.sort( function (a,b){ return b.value - a.value });
let sum = 0;
while (M > 1) {
let top = pq.pop();
sum += top.value;
top.j--;
let obj = {
value: A[top.i] / A[top.j],
i: top.i,
j: top.j
};
pq.push(obj);
pq.sort( function (a,b){ return b.value - a.value });
M--;
}
sum += pq.pop().value;
return sum;
}
let A = [ 1, 2, 3, 5 ];
let M = 2;
console.log(SumofMfractions(A, M));
|
Time Complexity: O(M * logN)
Auxiliary Space: O(N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...