Open In App

Find the pairs of IDs from two arrays having sum less than target closest to it

Last Updated : 17 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given two arrays arr1[] and arr2[] of pairs of the form {ID, value} of size N and M respectively and an integer target, the task is to find all the pairs of IDs from both the arrays such that the sum of the values of the pairs is maximum and has a value at most M.

Examples:

Input: arr1[] = [[1, 2000], [2, 3000], [3, 2000]], arr2[] = [[1, 2500], [2, 3000], [3, 3000]], target = 6000
Output:
2 2
2 3
Explanation:
Following are the pairs of elements from the two arrays arr1[] and arr2[]:

  • (arr1[2], arr2[2]): The sum of elements 3000 + 3000 = 6000(= target) and closest to the value target. Print the IDs as (2, 2).
  • (arr1[2], arr2[3]): The sum of elements 3000 + 3000 = 6000(= target) and closest to the value target. Print the IDs as (2, 3).

Input: arr1[] = [[1, 2000], [2, 3000], [3, 2000]], arr2[] = [[1, 3000], [2, 3000]], target = 5500
Output:
1 1
1 2
3 1
3 2

Approach: The given problem can be solved using the TreeMap Data Structure to store the array elements arr1[] and efficiently find the pair for every element in the other array arr2[]. Below are the steps:

  • Create a TreeMap where the key is the value of the array element and the value is the list of IDs.
  • Iterate the array arr1[] and insert its elements into the TreeMap.
  • Initialize a variable, say closestTarget to keep track of the closest value to the target and not exceeding it.
  • Initialize an ArrayList result to store all the possible pairs of IDs.
  • Iterate the array arr2[] and for every element calculate the remaining value to be searched in the TreeMap.
    • If the remaining value, say (target – arr2[i]) is less than 0, then the pair cannot be formed so continue the iteration.
    • Use the floorKey() function of the TreeMap to find a value less than or equal to the remaining value. If the returned value of the above function is null, then no corresponding element is found.
    • If the returned value, say currentTarget is greater than closestTarget, then update closestTarget and re-initialize the arrayList result[] to a new list.
    • Iterate through the list of ids whose key is currentTarget and add all possible combinations of IDs pairs into the result list.
  • After completing the above steps, print all the pairs of IDs stored in the ArrayList result[].

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
// Function to find pairs of ids with
// sum of values closest to the target
// but not exceeding the target
void closestPair(vector<vector<int> > arr1, vector<vector<int> > arr2, int target)
{
    // Initialize map having array
    // element value as key and list of
    // ids as value in the map
    map<int, vector<int> > valueToIds;
 
    // list to store all answer pairs
    vector<vector<int> > result;
 
    // Keeps the track of maximum sum
    // of pair values not exceeding target
    int closestTarget = 0;
 
    // Iterate through the array arr1 and
    // add all elements in the map
    for (vector<int> a : arr1) {
        int val = a[1], id = a[0];
        if (valueToIds.find(val) == valueToIds.end())
            valueToIds[val] = vector<int>();
        valueToIds[val].push_back(id);
    }
 
    for (vector<int> b : arr2) {
        // Find the corresponding value
        // to be found
        int remaining = target - b[1];
 
        if (remaining < 0)
            continue;
 
        // Find a value which is close to
        // desired value, not exceeding it
        map<int, vector<int> >::iterator it = valueToIds.lower_bound(remaining);
        if (it == valueToIds.end())
            continue;
 
        int floor = it->first;
 
        int currentTarget = b[1] + floor;
 
        if (currentTarget >= closestTarget) {
            if (currentTarget > closestTarget) {
                // Update closestTarget and reset
                // result list
                closestTarget = currentTarget;
                result.clear();
            }
 
            // Add all possible pairs in
            // result list
            for (int id : valueToIds[floor])
                result.push_back({ id, b[0] });
        }
    }
 
    // Print all the id pairs
    for (vector<int> ans : result) {
        cout << ans[0] << " " << ans[1] << endl;
    }
}
 
// Driver Code
int main()
{
    vector<vector<int> > arr1
        = { { 1, 2000 }, { 2, 3000 }, { 3, 2000 } };
    vector<vector<int> > arr2 = { { 1, 3000 },
                                   { 2, 3000 } };
    int target = 5500;
 
    closestPair(arr1, arr2, target);
 
    return 0;
}


Java




// Java program for the above approach
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Function to find pairs of ids with
    // sum of values closest to the target
    // but not exceeding the target
    public static void closestPair(
        int[][] arr1, int[][] arr2, int target)
    {
 
        // Initialize TreeMap having array
        // element value as key and list of
        // ids as value in the TreeMap
        TreeMap<Integer, List<Integer> > valueToIds
            = new TreeMap<>();
 
        // list to store all answer pairs
        List<int[]> result = new ArrayList<>();
 
        // Keeps the track of maximum sum
        // of pair values not exceeding target
        int closestTarget = 0;
 
        // Iterate through the array arr1 and
        // add all elements in the TreeMap
        for (int[] a : arr1) {
 
            int val = a[1], id = a[0];
            valueToIds.putIfAbsent(
                val, new ArrayList<>());
            valueToIds.get(val).add(id);
        }
 
        for (int[] b : arr2) {
 
            // Find the corresponding value
            // to be found
            int remaining = target - b[1];
 
            if (remaining < 0)
                continue;
 
            // Find a value which is close to
            // desired value, not exceeding it
            Integer floor = valueToIds.floorKey(
                remaining);
 
            // No value found which is less
            // than or equal to floor
            if (floor == null)
                continue;
 
            int currentTarget = b[1] + floor;
 
            if (currentTarget >= closestTarget) {
                if (currentTarget > closestTarget) {
 
                    // Update closeTarget and reset
                    // result list
                    closestTarget = currentTarget;
                    result = new ArrayList<>();
                }
 
                // Add all possible pairs in
                // result list
                for (int id : valueToIds.get(floor))
                    result.add(
                        new int[] { id, b[0] });
            }
        }
 
        // Print all the id pairs
        for (int[] ans : result) {
            System.out.println(
                ans[0] + " " + ans[1]);
        }
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int[][] arr1
            = { { 1, 2000 }, { 2, 3000 }, { 3, 2000 } };
        int[][] arr2 = { { 1, 3000 },
                         { 2, 3000 } };
        int target = 5500;
 
        closestPair(arr1, arr2, target);
    }
}


Python3




from bisect import bisect_right
 
def closestPair(arr1, arr2, target):
    # Create a dictionary to store the array elements
    value_to_ids = {}
    for a in arr1:
        val, id = a[1], a[0]
        if val not in value_to_ids:
            value_to_ids[val] = []
        value_to_ids[val].append(id)
    # Create a list to store the closest pairs
    closest_pairs = []
    closest_target = 0
    # Iterate through arr2
    for b in arr2:
        remaining = target - b[1]
        if remaining < 0:
            continue
        # Find the closest value to remaining in value_to_ids
        closest_val = bisect_right(sorted(value_to_ids.keys()), remaining)
        if closest_val == 0:
            continue
        closest_val = sorted(value_to_ids.keys())[closest_val - 1]
        current_target = b[1] + closest_val
        if current_target >= closest_target:
            if current_target > closest_target:
                closest_target = current_target
                closest_pairs = []
            for id in value_to_ids[closest_val]:
                closest_pairs.append((id, b[0]))
    # Print all the id pairs
    for pair in closest_pairs:
        print(pair[0], pair[1])
         
# Driver Code
if __name__ == "__main__":
    arr1 = [[1, 2000], [2, 3000], [3, 2000]]
    arr2 = [[1, 3000], [2, 3000]]
    target = 5500
 
    closestPair(arr1, arr2, target)


C#




using System;
using System.Collections.Generic;
 
class GFG
{
   
  // Function to find pairs of ids with
  // sum of values closest to the target
  // but not exceeding the target
  public static void closestPair(int[][] arr1,
                                 int[][] arr2,
                                 int target)
  {
     
    // Initialize Dictionary having array
    // element value as key and list of
    // ids as value in the Dictionary
    Dictionary<int, List<int>> valueToIds = new Dictionary<int, List<int>>();
 
    // list to store all answer pairs
    List<int[]> result = new List<int[]>();
 
    // Keeps the track of maximum sum
    // of pair values not exceeding target
    int closestTarget = 0;
 
    // Iterate through the array arr1 and
    // add all elements in the Dictionary
    foreach (int[] a in arr1) {
      int val = a[1], id = a[0];
      if (!valueToIds.ContainsKey(val)) {
        valueToIds[val] = new List<int>();
      }
      valueToIds[val].Add(id);
    }
 
    foreach (int[] b in arr2)
    {
       
      // Find the corresponding value
      // to be found
      int remaining = target - b[1];
 
      if (remaining < 0) {
        continue;
      }
 
      // Find a value which is close to
      // desired value, not exceeding it
      int? floor = null;
      foreach (int key in valueToIds.Keys) {
        if (key <= remaining) {
          floor = floor == null ? key : Math.Max(floor.Value, key);
        }
      }
 
      // No value found which is less
      // than or equal to floor
      if (floor == null) {
        continue;
      }
 
      int currentTarget = b[1] + floor.Value;
 
      if (currentTarget >= closestTarget) {
        if (currentTarget > closestTarget) {
          // Update closeTarget and reset
          // result list
          closestTarget = currentTarget;
          result = new List<int[]>();
        }
 
        // Add all possible pairs in
        // result list
        foreach (int id in valueToIds[floor.Value]) {
          result.Add(new int[] { id, b[0] });
        }
      }
    }
 
    // Print all the id pairs
    foreach (int[] ans in result) {
      Console.WriteLine(ans[0] + " " + ans[1]);
    }
  }
 
  // Driver Code
  public static void Main(string[] args) {
    int[][] arr1 = new int[][] {
      new int[] { 1, 2000 },
      new int[] { 2, 3000 },
      new int[] { 3, 2000 }
    };
    int[][] arr2 = new int[][] {
      new int[] { 1, 3000 },
      new int[] { 2, 3000 }
    };
    int target = 5500;
 
    closestPair(arr1, arr2, target);
  }
}


Javascript




function closestPair(arr1, arr2, target)
{
 
    // Create a dictionary to store the array elements
    let value_to_ids = {};
    for (let a of arr1) {
        let val = a[1], id = a[0];
        if (!value_to_ids[val]) {
            value_to_ids[val] = [];
        }
        value_to_ids[val].push(id);
    }
     
    // Create a list to store the closest pairs
    let closest_pairs = [];
    let closest_target = 0;
     
    // Iterate through arr2
    for (let b of arr2) {
        let remaining = target - b[1];
        if (remaining < 0) {
            continue;
        }
         
        // Find the closest value to remaining in value_to_ids
        let keys = Object.keys(value_to_ids).sort((a, b) => a - b);
        let closest_val = keys.find(k => k >= remaining);
        if (!closest_val) {
            continue;
        }
        let current_target = b[1] + closest_val;
        if (current_target >= closest_target) {
            if (current_target > closest_target) {
                closest_target = current_target;
                closest_pairs = [];
            }
            for (let id of value_to_ids[closest_val]) {
                closest_pairs.push([id, b[0]]);
            }
        }
    }
     
    // Print all the id pairs
    for (let pair of closest_pairs) {
        console.log(pair[0], pair[1]);
    }
}
 
// Driver Code
if (typeof require === 'undefined' || require.main === module) {
    let arr1 = [[1, 2000], [2, 3000], [3, 2000]];
    let arr2 = [[1, 3000], [2, 3000]];
    let target = 5500;
 
    closestPair(arr1, arr2, target);
}
 
// This code is contributed by aadityamaharshi21.


Output:

1 1
3 1
1 2
3 2

Time Complexity: O(N*log N + M)
Auxiliary Space: O(N*M)



Similar Reads

Count the number of words having sum of ASCII values less than and greater than k
Given a string, the task is to count the number of words whose sum of ASCII values is less than and greater than or equal to given k. Examples: Input: str = "Learn how to code", k = 400Output:Number of words having the sum of ASCII less than k = 2Number of words having the sum of ASCII greater than or equal to k = 2 Input: str = "Geeks for Geeks",
11 min read
Maximum sum subarray having sum less than given sum using Set
Given an array arr[] of length N and an integer K, the task is the find the maximum sum subarray with a sum less than K.Note: If K is less than the minimum element, then return INT_MIN. Examples: Input: arr[] = {-1, 2, 2}, K = 4 Output: 3 Explanation: The subarray with maximum sum which is less than 4 is {-1, 2, 2}. The subarray {2, 2} has maximum
7 min read
Maximum sum subarray having sum less than or equal to given sum
Given an array of non-negative integers and a sum. We have to find sum of the subarray having a maximum sum less than or equal to the given sum in the array. Note: Given array contains only non-negative integers. Examples: Input: arr[] = { 1, 2, 3, 4, 5 } sum = 11Output: 10Subarray having maximum sum is { 1, 2, 3, 4 }Input: arr[] = { 2, 4, 6, 8, 10
10 min read
Count of alphabets having ASCII value less than and greater than k
Given a string, the task is to count the number of alphabets having ASCII values less than and greater than or equal to a given integer k. Examples: Input: str = "GeeksForGeeks", k = 90Output:3, 10G, F, G have ascii values less than 90.e, e, k, s, o, r, e, e, k, s have ASCII values greater than or equal to 90 Input: str = "geeksforgeeks", k = 90Out
11 min read
Count pairs having Bitwise XOR less than K from given array
Given an array arr[]of size N and an integer K, the task is to count the number of pairs from the given array such that the Bitwise XOR of each pair is less than K. Examples: Input: arr = {1, 2, 3, 5} , K = 5 Output: 4 Explanation: Bitwise XOR of all possible pairs that satisfy the given conditions are: arr[0] ^ arr[1] = 1 ^ 2 = 3 arr[0] ^ arr[2] =
16 min read
Count maximum number of disjoint pairs having one element not less than K times the other
Given an array arr[] and a positive integer K, the task is to find the maximum count of disjoint pairs (arr[i], arr[j]) such that arr[j] ? K * arr[i]. Examples: Input: arr[] = { 1, 9, 4, 7, 3 }, K = 2Output: 2Explanation:There can be 2 possible pairs that can formed from the given array i.e., (4, 1) and (7, 3) that satisfy the given conditions. Inp
6 min read
Reduce sum of same-indexed elements of two arrays to less than K by rearranging the second array
Given two arrays arr1[] and arr2[], both of size N and an integer X, the task is to check if the sum of same-indexed elements of both the arrays at corresponding indices can be made at most K after rearranging the second array. If it is possible then print "Yes" else print "No". Examples: Input: arr1[] = {1, 2, 3}, arr2[] = {1, 1, 2}, X = 4Output:
6 min read
Find minimum integer greater than B that is product of two values less than A
Given 2 positive integers A and B, the task is to find the minimum possible integer C, which is greater than or equal to B and is a product of two positive integers, both of which are less than or equal to A. Examples: Input: A = 5, B = 7Output: 8Explanation: 8 can be represented as a product of 2 positive integers less than 5. i.e. 2*4 = 8. Also,
6 min read
Largest subset having with sum less than equal to sum of respective indices
Given an array arr[], the task is to find the length of the largest subset with the sum of elements less than or equal to the sum of its indexes(1-based indexing). Examples: Input: arr[] = {1, 7, 3, 5, 9, 6, 6} Output: 5 Explanation: Largest Subset is {1, 3, 5, 6, 6} Sum of indexes = 1 + 3 + 4 + 6 + 7 = 21 Sum of elements = 1 + 3 + 5 + 6 + 6 = 21 I
8 min read
Largest number less than N with digit sum greater than the digit sum of N
Given an integer N, the task is to find the greatest number less than N such that the sum of its digits is greater than the sum of the digits of N. If the condition isn't satisfied for any number then print -1.Examples: Input: N = 100 Output: 99 99 is the largest number less than 100 sum of whose digits is greater than the sum of the digits of 100I
9 min read