Open In App

Kth largest pairwise product possible from given two Arrays

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

Given two arrays arr[] and brr[] containing integers. The task is to find the Kth largest product of a pair (arr[i], brr[j]).

Examples: 

Input: arr[] = {1, -2, 3}, brr[] = {3, -4, 0}, K = 3
Output: 3
Explanation: All product combinations in descending order are : [9, 8, 3, 0, 0, 0, -4, -6, -12] and 3rd largest element is 3.

Input: arr[] = {-1, -5, -3}, brr[] = {-3, -4, 0}, K =5
Output: 4
Explanation: All product combinations in descending order are : [20, 15, 12, 9, 4, 3, 0, 0, 0] and 5th largest element is 4.

 

Naive Approach: Generate all the possible products combination for each element in array arr[] with each element in array brr[]. Then sort the array of results and return the Kth element of the results array.

C++




#include <bits/stdc++.h>
using namespace std;
int solve(int a[ ], int n, int b[ ], int m, int k) {
  vector<int> ans;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
 
      // take product
      int prod = a[i] * b[j];
      ans.push_back(prod);
    }
  }
 
  // Sort array in descending order
  sort(ans.begin(), ans.end(), greater<int>());
 
  // Finally return (k - 1)th index
  // as indexing begin from 0.
  return ans[k - 1];
}
 
// Driver code
int main()
{
 
  int arr[ ] = { 1, -2, 3 };
  int brr[ ] = { 3, -4, 0 };
  int K = 3;
  int n = sizeof(arr) / sizeof(int);
  int m = sizeof(brr) / sizeof(int);
   
  // Function Call
  int val = solve(arr, n, brr, m, K);
 
  cout << val;
 
  return 0;
}
 
// This code is contributed by hrithikgarg03188


Java




// Java code for the above approach
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
 
class GFG {
 
  static int solve(int[] a, int[] b, int k) {
    List<Integer> ans = new LinkedList<>();
    int n = a.length;
    int m = b.length;
 
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
 
        // take product
        int prod = a[i] * b[j];
        ans.add(prod);
      }
    }
 
    // Sort array in descending order
    Collections.sort(ans, (x, y) -> y - x);
 
    // Finally return (k - 1)th index
    // as indexing begins from 0.
    return (ans.get(k - 1));
  }
 
  // Driver Code
  public static void main(String[] args)
  {
 
    int[] arr = { 1, -2, 3 };
    int[] brr = { 3, -4, 0 };
    int K = 3;
 
    // Function Call
    int val = solve(arr, brr, K);
 
    System.out.println(val);
 
  }
}
 
// This code is contributed by 29AjayKumar


Python3




# Python program for above approach
def solve(a, b, k):
    ans = []
    n = len(a)
    m = len(b)
 
    for i in range(n):
        for j in range(m):
 
            # take product
            prod = a[i]*b[j]
            ans.append(prod)
 
    # Sort array in descending order
    ans.sort(reverse = True)
 
    # Finally return (k-1)th index
    # as indexing begins from 0.
    return (ans[k-1])
 
 
# Driver Code
arr = [1, -2, 3]
brr = [3, -4, 0]
K = 3
 
# Function Call
val = solve(arr, brr, K)
 
print(val)


C#




// C# code for the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
 
  static int solve(int[] a, int[] b, int k) {
    List<int> ans = new List<int>();
    int n = a.Length;
    int m = b.Length;
 
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
 
        // take product
        int prod = a[i] * b[j];
        ans.Add(prod);
      }
    }
 
    // Sort array in descending order
    ans.Sort((x, y) => y - x);
 
    // Finally return (k - 1)th index
    // as indexing begins from 0.
    return (ans[k - 1]);
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
 
    int[] arr = { 1, -2, 3 };
    int[] brr = { 3, -4, 0 };
    int K = 3;
 
    // Function Call
    int val = solve(arr, brr, K);
 
    Console.WriteLine(val);
 
  }
}
 
// This code is contributed by 29AjayKumar


Javascript




<script>
      // JavaScript code for the above approach
      function solve(a, b, k)
      {
          ans = []
          n = a.length
          m = b.length
 
          for (let i = 0; i < n; i++)
          {
              for (let j = 0; j < m; j++)
              {
 
                  // take product
                  prod = a[i] * b[j]
                  ans.push(prod)
              }
          }
           
          // Sort array in descending order
          ans.sort(function (a, b) { return b - a })
 
          // Finally return (k - 1)th index
          // as indexing begins from 0.
          return (ans[k - 1])
      }
 
      // Driver Code
      arr = [1, -2, 3]
      brr = [3, -4, 0]
      K = 3
 
      // Function Call
      val = solve(arr, brr, K)
 
      document.write(val)
       
// This code is contributed by Potta Lokesh
  </script>


Output: 

3

 

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

Efficient Approach: This problem can be solved by using the Greedy Approach and Heaps. Follow the steps below to solve the given problem. 

  • Sort the brr[] array.
  • Keep larger size array in the array arr[].
  • Create a max heap to store the elements with their respective indices.
  • Traverse each element from array arr[]. The element can be either positive or negative.
  • Positive: Multiply current element from arr[] with the largest element of sorted array brr[]. To ensure that maximum element is obtained.
  • Negative: In this case multiply with the smallest value, i.e. with the first element from array brr[]. This is due to the property of negation, as a larger value can be obtained by multiplying with the smallest one.
  • Insert three values into heap such that : ( product, i, j ) where i & j are the indices of arrays arr[] and brr[].
  • Now run a for loop K times and pop elements from the heap.
  • Now check if the value present at arr[i] is positive or negative
  • Positive: So next_j = ( current_j – 1) because as max heap is been used, all the higher indices might have been already popped from the heap.
  • Negative:  next_j = (current_j +1) because all the smaller values yielding larger elements might have been already popped from the heap.
  • Finally, return the answer

Note:  Max heap is implemented with the help of min-heap, by negating the signs of the values while inserting them into the heap in Python.

Below is the implementation of the above approach.

C++




// C++program for above approach
#include<bits/stdc++.h>
using namespace std;
 
class Pair {
  public:
  int val;
  int i;
  int j;
 
  Pair(int val, int i, int j)
  {
    this->val = val;
    this->i = i;
    this->j = j;
  }
};
 
struct comparator {
  bool operator()(Pair const& p1, Pair const& p2)
  {
     
    // return "true" if "p1" is ordered
    // before "p2", for example:
    return p1.val < p2.val;
  }
};
 
int solve(int* a, int* b,  int k)
{
   
  // Sorting array b in ascending order
  sort(b, b + k);
  int n = k;
  int m = k;
 
  // Checking if size(a) > size(b)
  if (n < m) {
    // Otherwise swap the arrays
    return solve(b, a, k);
  }
 
  // Create a max heap
  priority_queue<Pair, vector<Pair>, comparator> heap;
 
  // Traverse all elements in array a
  for (int i = 0; i < n; i++) {
    int curr = a[i];
     
    // curr element is negative
    if (curr < 0) {
       
      // Product with smallest value
      int val = curr * b[0];
       
      // Pushing the value and i as well jth index
      heap.push(Pair(val, i, 0));
    }
    else
    {
       
      // Product with largest value
      int val = curr * b[m - 1];
       
      // Pushing the value and i as well jth index
      heap.push(Pair(val, i, m - 1));
    }
  }
 
  // Subtract 1 due to zero indexing
  k--;
 
  // Remove k-1 largest items from heap
  for (int i = 0; i < k; i++) {
    Pair pair = heap.top();
    heap.pop();
    int val = pair.val;
    int iIndex = pair.i;
    int jIndex = pair.j;
     
    // if a[i] is negative, increment ith index
    int nextJ;
    if (a[iIndex] < 0) {
      nextJ = jIndex + 1;
    }
    else
    {
       
      // if a[i] is positive, decrement jth index
      nextJ = jIndex - 1;
    }
     
    // if index is valid
    if (nextJ >= 0 && nextJ < m) {
      int newVal = a[iIndex] * b[nextJ];
       
      // Pushing new_val in the heap
      heap.push(Pair(newVal, iIndex, nextJ));
    }
  }
 
  // Finally return first val in the heap
  return heap.top().val;
}
 
int main()
{
  int arr[] = { 1, -2, 3 };
  int brr[] = { 3, -4, 0 };
  int K = 3;
 
  // Function Call
  int val = solve(arr, brr, K);
 
  // Print the result
  cout << val << endl;
 
  return 0;
}
 
// The code is contributed by Nidhi goel.


Java




// Java program for above approach
 
import java.io.*;
import java.util.*;
 
class Pair {
  int val;
  int i;
  int j;
 
  public Pair(int val, int i, int j)
  {
    this.val = val;
    this.i = i;
    this.j = j;
  }
}
 
class GFG {
 
  static int solve(int[] a, int[] b, int k)
  {
    // Sorting array b in ascending order
    Arrays.sort(b);
    int n = a.length;
    int m = b.length;
 
    // Checking if size(a) > size(b)
    if (n < m) {
      // Otherwise swap the arrays
      return solve(b, a, k);
    }
 
    // Create a max heap
    PriorityQueue<Pair> heap = new PriorityQueue<>(
      (p1, p2) -> p2.val - p1.val);
 
    // Traverse all elements in array a
    for (int i = 0; i < n; i++) {
      int curr = a[i];
      // curr element is negative
      if (curr < 0) {
        // Product with smallest value
        int val = curr * b[0];
        // Pushing the value and i as well jth index
        heap.add(new Pair(val, i, 0));
      }
      else {
        // Product with largest value
        int val = curr * b[m - 1];
        // Pushing the value and i as well jth index
        heap.add(new Pair(val, i, m - 1));
      }
    }
 
    // Subtract 1 due to zero indexing
    k--;
 
    // Remove k-1 largest items from heap
    for (int i = 0; i < k; i++) {
      Pair pair = heap.poll();
      int val = pair.val;
      int iIndex = pair.i;
      int jIndex = pair.j;
      // if a[i] is negative, increment ith index
      int nextJ;
      if (a[iIndex] < 0) {
        nextJ = jIndex + 1;
      }
      else {
        // if a[i] is positive, decrement jth index
        nextJ = jIndex - 1;
      }
      // if index is valid
      if (nextJ >= 0 && nextJ < m) {
        int newVal = a[iIndex] * b[nextJ];
        // Pushing new_val in the heap
        heap.add(new Pair(newVal, iIndex, nextJ));
      }
    }
 
    // Finally return first val in the heap
    return heap.peek().val;
  }
 
  public static void main(String[] args)
  {
    int[] arr = { 1, -2, 3 };
    int[] brr = { 3, -4, 0 };
    int K = 3;
 
    // Function Call
    int val = solve(arr, brr, K);
 
    // Print the result
    System.out.println(val);
  }
}
 
// This code is contributed by lokesh.


Python3




# Python program for above approach
from heap import heappush as push, heappop as pop
 
 
def solve(a, b, k):
 
    # Sorting array b in ascending order
    b.sort()
    n, m = len(a), len(b)
 
    # Checking if size(a) > size(b)
 
    if (n < m):
 
        # Otherwise swap the arrays
 
        return solve(b, a, k)
 
    heap = []
 
    # Traverse all elements in array a
    for i in range(n):
 
        curr = a[i]
 
        # curr element is negative
        if (curr < 0):
 
            # Product with smallest value
            val = curr * b[0]
 
            # Pushing negative val due to max heap
            # and i as well jth index
            push(heap, (-val, i, 0))
 
        else:
 
            # Product with largest value
            val = curr * b[-1]
 
            # Pushing negative val due to max heap
            # and i as well jth index
            push(heap, (-val, i, m-1))
 
    # Subtract 1 due to zero indexing
    k = k-1
 
    # Remove k-1 largest items from heap
    for _ in range(k):
 
        val, i, j = pop(heap)
        val = -val
 
        # if a[i] is negative, increment ith index
 
        if (a[i] < 0):
            next_j = j + 1
 
        # if a[i] is positive, decrement jth index
        else:
            next_j = j-1
 
        # if index is valid
        if (0 <= next_j < m):
 
            new_val = a[i] * b[next_j]
 
            # Pushing new_val in the heap
            push(heap, (-new_val, i, next_j))
 
    # Finally return first val in the heap
    return -(heap[0][0])
 
 
# Driver Code
arr = [1, -2, 3]
brr = [3, -4, 0]
K = 3
 
# Function Call
val = solve(arr, brr, K)
 
# Print the result
print(val)


C#




// C# program for above approach
 
using System;
using System.Collections.Generic;
 
class Pair : IComparable<Pair>
{
    public int val;
    public int i;
    public int j;
 
    public Pair(int val, int i, int j)
    {
        this.val = val;
        this.i = i;
        this.j = j;
    }
 
    public int CompareTo(Pair other)
    {
        return this.val - other.val;
    }
}
 
public class GFG
{
    static int solve(int[] a, int[] b, int k)
    {
        // Sorting array b in ascending order
        Array.Sort(b);
        int n = a.Length;
        int m = b.Length;
 
        // Checking if size(a) > size(b)
        if (n < m)
        {
            // Otherwise swap the arrays
            return solve(b, a, k);
        }
 
        // Create a max heap
        SortedSet<Pair> heap = new SortedSet<Pair>();
 
        // Traverse all elements in array a
        for (int i = 0; i < n; i++)
        {
            int curr = a[i];
            // curr element is negative
            if (curr < 0)
            {
                // Product with smallest value
                int val = curr * b[0];
                // Pushing the value and i as well jth index
                heap.Add(new Pair(val, i, 0));
            }
            else
            {
                // Product with largest value
                int val = curr * b[m - 1];
                // Pushing the value and i as well jth index
                heap.Add(new Pair(val, i, m - 1));
            }
        }
 
        // Subtract 1 due to zero indexing
        k--;
 
        // Remove k-1 largest items from heap
        for (int i = 0; i < k; i++)
        {
            Pair pair = heap.Max;
            heap.Remove(pair);
            int iIndex = pair.i;
            int jIndex = pair.j;
            // if a[i] is negative, increment ith index
            int nextJ;
            if (a[iIndex] < 0)
            {
                nextJ = jIndex + 1;
            }
            else
            {
                // if a[i] is positive, decrement jth index
                nextJ = jIndex - 1;
            }
            // if index is valid
            if (nextJ >= 0 && nextJ < m)
            {
                int newVal = a[iIndex] * b[nextJ];
                // Pushing new_val in the heap
                heap.Add(new Pair(newVal, iIndex, nextJ));
            }
        }
 
        // Finally return first val in the heap
        return heap.Max.val;
    }
 
    static void Main(string[] args)
    {
        int[] arr = { 1, -2, 3 };
        int[] brr = { 3, -4, 0 };
        int K = 3;
         
        // Function Call
        int val = solve(arr, brr, K);
 
        // Print the result
        Console.WriteLine(val);
    }
}


Javascript




// Javascript program for above approach
class Pair {
     
  constructor(val, i, j)
  {
    this.val = val;
    this.i = i;
    this.j = j;
  }
}
 
function sortFunction(a, b) {
    return a[0] - b[0];
}
 
function solve(a, b, k)
{
   
  // Sorting array b in ascending order
  b.sort();
  let n = k;
  let m = k;
 
  // Checking if size(a) > size(b)
  if (n < m) {
    // Otherwise swap the arrays
    return solve(b, a, k);
  }
 
  // Create a max heap
  let heap = [];
 
  // Traverse all elements in array a
  for (let i = 0; i < n; i++) {
    let curr = a[i];
     
    // curr element is negative
    if (curr < 0) {
       
      // Product with smallest value
      let val = curr * b[0];
       
      // Pushing the value and i as well jth index
      heap.push([val, i, 0]);
      heap.sort(sortFunction);
    }
    else
    {
       
      // Product with largest value
      let val = curr * b[m - 1];
       
      // Pushing the value and i as well jth index
      heap.push([val, i, m - 1]);
      heap.sort(sortFunction);
    }
  }
 
  // Subtract 1 due to zero indexing
  k--;
 
  // Remove k-1 largest items from heap
  for (let i = 0; i < k; i++) {
    let pair = heap[heap.length - 1];
    heap.pop();
    let val = pair[0];
    let iIndex = pair[1];
    let jIndex = pair[2];
     
    // if a[i] is negative, increment ith index
    let nextJ = 0;
    if (a[iIndex] < 0) {
      nextJ = jIndex + 1;
    }
    else
    {
       
      // if a[i] is positive, decrement jth index
      nextJ = jIndex - 1;
    }
     
    // if index is valid
    if (nextJ >= 0 && nextJ < m) {
      let newVal = a[iIndex] * b[nextJ];
       
      // Pushing new_val in the heap
      heap.push([newVal, iIndex, nextJ]);
      heap.sort(sortFunction);
    }
  }
 
  // Finally return first val in the heap
  return heap[heap.length - 1][0];
}
 
let arr =  [1, -2, 3];
let brr =  [3, -4, 0];
let K = 3;
 
// Function Call
let val = solve(arr, brr, K);
 
// Print the result
console.log(val);
 
// The code is contributed by Nidhi goel.


Output: 

3

 

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



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads