Open In App

Maximum sum with limited queries

Last Updated : 29 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of n integers in sorted order, find the maximum number of largest elements that can be selected from the array such that the sum is less than or equal to k. You can select an element any number of times. The sum of the selected elements should be maximized. You can query the value of any element at most 50 times. If you exceed this limit, you cannot select any element. Assume that there is an infinite supply of elements available and the values of elements are pairwise distinct.

Examples:

Input: n = 3, k = 5, arr[] = {2, 4, 6}
Output: 1
Explanation: The elements are [2, 4, 6] and the value of k is 5. So, we can pick only 1 element that is 4 (since we always picks the largest one).

Input: n = 4, k = 9, arr[] = {1, 2, 3, 4}
Output: 3
Explanation: The elements are [1, 2, 3, 4] and the value of k is 9. So we can pick element 4, 2 times and element 1, 1 time.

Approach: To solve the problem follow the below idea:

As the elements are arranged in sorted order, binary search must be used to discover the solution and we can use the get() function only 50 times.

Below are the steps for the above approach:

  • Initializes a variable count = 0 and a map hm to store the results of the binary search for each element.
  • Run a loop until k is 0 or all elements in the array have been searched.
  • Initialize low = 0 and high = n-1 and search for the largest element in the Element array that is less than or equal to k.
  • If the binary search finds an element less than or equal to k, update low = mid+1, else update high = mid -1 to continue the search for the next smallest element.
  • Check if high == 1, and break the loop.
  • Calculate the number of times the largest element less than or equal to k appears in the Element array, and add this value to the count variable, count += (k / hm.get(high)).
  • Subtract the total value of the largest element less than or equal to k from k, k -= (k / hm.get(high)) * hm.get(high).
  • The loop is repeated with the new value of k.
  • Return the value of the count.

Below is the code for the above approach:

C++




#include <iostream>
#include <unordered_map>
using namespace std;
 
// Element class
class Element {
private:
    int* arr;
public:
    Element(int* arr) {
        this->arr = arr;
    }
    long Get(int i) {
        return arr[i];
    }
};
 
class GFG {
private:
    static Element* element;
public:
    GFG(Element* element) {
        GFG::element = element;
    }
    static long Find(int n, long k) {
        int low = 0, high = n - 1;
       
          // variables to store the reult of binary search
        int count = 0;
        unordered_map<int, long> hm;
          // Loop to search all element
        while (k > 0) {
            low = 0;
               
            while (low <= high) {
               
                  // find mid index
                int mid = (low + high) / 2;
                long temp;
                if (hm.find(mid) == hm.end())
                    temp = element->Get(mid);
                else
                    temp = hm[mid];
                hm[mid] = temp;
                if (temp <= k)
                    low = mid + 1;
                else
                    high = mid - 1;
            }
            if (high == -1)
                break;
           
              // Subtract the total value of the largest
              // element less than or equal to k from k
            count += (int)(k / hm[high]);
            k -= (k / hm[high]) * hm[high];
        }
        return count;
    }
};
 
Element* GFG::element;
 
// Driver code
int main() {
    int n = 3;
    long k = 5;
    int arr[] = { 2, 4, 6 };
    Element* element = new Element(arr);
    GFG* gfg = new GFG(element);
    cout << GFG::Find(n, k) << endl;
    return 0;
}


Java




// Java code for the above approach:
import java.util.*;
 
class Element {
    int[] arr;
    public Element(int[] arr) { this.arr = arr; }
    public long get(int i) { return arr[i]; }
}
 
class GFG {
    static Element element;
    GFG(Element element) { this.element = element; }
    static long find(int n, long k)
    {
        int low = 0, high = n - 1;
        int count = 0;
        Map<Integer, Long> hm = new HashMap<>();
        while (k > 0) {
            low = 0;
            while (low <= high) {
                int mid = (low + high) / 2;
                long temp;
                if (!hm.containsKey(mid))
                    temp = element.get(mid);
                else
                    temp = hm.get(mid);
 
                hm.put(mid, temp);
                if (temp <= k)
                    low = mid + 1;
                else
                    high = mid - 1;
            }
            if (high == -1)
                break;
            count += (k / hm.get(high));
 
            k -= (k / hm.get(high)) * hm.get(high);
        }
        return count;
    }
 
    // Drivers code
    public static void main(String[] args)
    {
        int n = 3;
        long k = 5;
        int[] arr = { 2, 4, 6 };
        element = new Element(arr);
 
        // Function Call
        System.out.println(find(n, k));
    }
}


Python3




# Element class
class Element:
    def __init__(self, arr):
        self.arr = arr
     
    def Get(self, i):
        return self.arr[i]
 
class GFG:
    element = None
     
    def __init__(self, element):
        GFG.element = element
     
    @staticmethod
    def Find(n, k):
        low = 0
        high = n - 1
         
        # variables to store the reult of binary search
        count = 0
        hm = {}
         
        # Loop to search all element
        while k > 0:
            low = 0
            while low <= high:
               
                # find mid index
                mid = (low + high) // 2
                temp = GFG.element.Get(mid) if mid not in hm else hm[mid]
                hm[mid] = temp
                if temp <= k:
                    low = mid + 1
                else:
                    high = mid - 1
            if high == -1:
                break
             
            # Subtract the total value of the largest
            # element less than or equal to k from k
            count += k // hm[high]
            k -= (k // hm[high]) * hm[high]
        return count
 
# Driver code
n = 3
k = 5
arr = [2, 4, 6]
element = Element(arr)
gfg = GFG(element)
print(GFG.Find(n, k))


C#




// c# code for the above approach:
 
using System;
using System.Collections.Generic;
 
public class Element
{
    private int[] arr;
 
    public Element(int[] arr)
    {
        this.arr = arr;
    }
 
    public long Get(int i)
    {
        return arr[i];
    }
}
 
public class GFG
{
    private static Element element;
 
    public GFG(Element element)
    {
        GFG.element = element;
    }
 
    public static long Find(int n, long k)
    {
        int low = 0, high = n - 1;
        int count = 0;
        Dictionary<int, long> hm = new Dictionary<int, long>();
 
        while (k > 0)
        {
            low = 0;
            while (low <= high)
            {
                int mid = (low + high) / 2;
                long temp;
                if (!hm.ContainsKey(mid))
                    temp = element.Get(mid);
                else
                    temp = hm[mid];
 
                hm[mid] = temp;
                if (temp <= k)
                    low = mid + 1;
                else
                    high = mid - 1;
            }
            if (high == -1)
                break;
 
            count += (int)(k / hm[high]);
            k -= (k / hm[high]) * hm[high];
        }
        return count;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int n = 3;
        long k = 5;
        int[] arr = { 2, 4, 6 };
        element = new Element(arr);
 
        // Function Call
        Console.WriteLine(Find(n, k));
    }
}


Javascript




// Class to store the array
class Element {
    constructor(arr) {
        this.arr = arr;
    }
    get(i) {
        return this.arr[i];
    }
}
 
let element;
// Function to find the count
function find(n, k) {
    let low = 0,
        high = n - 1;
    let count = 0;
    let hm = new Map();
    while (k > 0) {
        low = 0;
        while (low <= high) {
            let mid = Math.floor((low + high) / 2);
            let temp;
            if (!hm.has(mid)) temp = element.get(mid);
            else temp = hm.get(mid);
 
            hm.set(mid, temp);
            if (temp <= k) low = mid + 1;
            else high = mid - 1;
        }
        if (high == -1) break;
        count += Math.floor(k / hm.get(high));
         
        // Subtract the total value of the largest
        // element less than or equal to k from k
        k -= Math.floor(k / hm.get(high)) * hm.get(high);
    }
    return count;
}
 
// Driver code
let n = 3;
let k = 5;
let arr = [2, 4, 6];
element = new Element(arr);
console.log("The number of ways are: " + find(n, k));


Output

1








Time Complexity: O(logN)
Auxiliary Space: O(logN)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads