Open In App

Sum of first M fractions formed from Array of primes

Last Updated : 25 Jan, 2023
Comments
Improve
Suggest changes
Like Article
Like
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)


Next Article

Similar Reads