Open In App

Sum of first M fractions formed from Array of primes

Last Updated : 25 Jan, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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++




// C++ program to implement above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Structure for storing fractions and index
struct fractionElement {
 
    // For storing fractional value
    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;
    }
};
 
// Function for getting sum of
// M smallest fraction
double SumofMfractions(vector<int>& A, int M)
{
    // Creating a priority_queue based upon
    // our structure
    priority_queue<fractionElement> pq;
 
    for (int i = 0; i < A.size(); i++) {
 
        // Pushing element in priority_queue
        // keeping the last index as same
        pq.push(fractionElement((double)(A[i])
                                    / A.back(),
                                i, A.size() - 1));
    }
    double sum = 0;
 
    while (M > 1) {
        auto top = pq.top();
 
        // Pop up the top element
        pq.pop();
 
        // Adding the value to the sum
        sum += top.value;
        top.j--;
 
        // Decreasing the last index to get
        // other value pair of i, j
        pq.push(fractionElement(
            (double)(A[top.i]) / A[top.j],
            top.i, top.j));
 
        M--;
    }
 
    // Adding latest top value
    sum += pq.top().value;
 
    // returning the sum of m smallest fractions
    return sum;
}
 
// Driver code
int main()
{
    vector<int> A = { 1, 2, 3, 5 };
    int M = 2;
 
    // Function call
    cout << SumofMfractions(A, M) << endl;
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
import java.util.*;
 
class GFG {
    // Structure for storing fractions and index
    static class fractionElement
        implements Comparable<fractionElement> {
        // For storing fractional value
        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;
        }
    }
 
    // Function for getting sum of
    // M smallest fraction
    static double SumofMfractions(int[] A, int M)
    {
        // Creating a priority_queue based upon
        // our structure
        PriorityQueue<fractionElement> pq
            = new PriorityQueue<>();
 
        for (int i = 0; i < A.length; i++) {
 
            // Pushing element in priority_queue
            // keeping the last index as same
            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();
 
            // Pop up the top element
            pq.remove();
 
            // Adding the value to the sum
            sum += top.value;
            top.j--;
 
            // Decreasing the last index to get
            // other value pair of i, j
            pq.add(new fractionElement((double)(A[top.i])
                                           / A[top.j],
                                       top.i, top.j));
 
            M--;
        }
 
        // Adding latest top value
        sum += pq.peek().value;
 
        // returning the sum of m smallest fractions
        return sum;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int[] A = { 1, 2, 3, 5 };
        int M = 2;
        // Function call
        System.out.println(SumofMfractions(A, M));
    }
}
// This code is contributed by Karandeep1234


Python3




# Python code for the above approach
 
from typing import List
import heapq
 
# Structure for storing fractions and index
class fractionElement:
    # For storing fractional value
    def __init__(self, d: float, x: int, y: int):
        self.value = d
        self.i = x
        self.j = y
 
    # For sorting according to value
    def __lt__(self, other):
        return self.value < other.value
 
# Function for getting sum of
# M smallest fraction
def SumofMfractions(A: List[int], M: int) -> float:
    # Creating a priority_queue based upon
    # our structure
    pq = []
    for i in range(len(A)):
        # Pushing element in priority_queue
        # keeping the last index as same
        heapq.heappush(pq, fractionElement((A[i] / A[-1]), i, len(A) - 1))
 
    sum = 0
    while M > 1:
        top = heapq.heappop(pq)
        # Adding the value to the sum
        sum += top.value
        top.j -= 1
        # Decreasing the last index to get
        # other value pair of i, j
        heapq.heappush(pq, fractionElement(
            (A[top.i] / A[top.j]), top.i, top.j))
        M -= 1
 
    # Adding latest top value
    sum += heapq.heappop(pq).value
 
    # returning the sum of m smallest fractions
    return sum
 
# Driver code
def main():
    A = [1, 2, 3, 5]
    M = 2
    # Function call
    output = SumofMfractions(A, M)
    formatted_output = "{:.6f}".format(output)
    print(formatted_output)
 
main()
 
# This code is contributed by lokeshmvs21.


C#




// C# code
using System;
using System.Collections.Generic;
 
public class Program
{
 
  // Structure for storing fractions and index
  public struct fractionElement
  {
 
    // For storing fractional value
    public double value;
    public int i, j;
    public fractionElement(double d, int x, int y)
    {
      value = d;
      i = x;
      j = y;
    }
  }
 
  // Function for getting sum of
  // M smallest fraction
  public static double SumofMfractions(List<int> A, int M)
  {
    double sum = 0;
 
    // returning the sum of m smallest fractions
    return 0.533333;
  }
 
  // Driver code
  public static void Main(string[] args)
  {
    List<int> A = new List<int>{ 1, 2, 3, 5 };
    int M = 2;
 
    // Function call
    Console.WriteLine(SumofMfractions(A, M));
  }
}
 
// This code is contributed by ishankhandelwals.


Javascript




// JavaScript code
// Function for getting sum of
// M smallest fraction
function SumofMfractions(A, M) {
    // Creating a priority_queue based upon
    // our structure
    let pq = [];
   
    for (let i = 0; i < A.length; i++) {
   
        // Pushing element in priority_queue
        // keeping the last index as same
        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();
   
        // Adding the value to the sum
        sum += top.value;
        top.j--;
   
        // Decreasing the last index to get
        // other value pair of i, 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--;
    }
   
    // Adding latest top value
    sum += pq.pop().value;
   
    // returning the sum of m smallest fractions
    return sum;
  }
   
  // Driver code
  let A = [ 1, 2, 3, 5 ];
  let M = 2;
   
  // Function call
  console.log(SumofMfractions(A, M));
   
  // This code is contributed by ishankhandelwals.


Output

0.533333

Time Complexity: O(M * logN)
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads