Skip to content
Related Articles
Get the best out of our app
GFG App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Kth largest pairwise product possible from given two Arrays

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

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)


My Personal Notes arrow_drop_up
Last Updated : 09 Feb, 2023
Like Article
Save Article
Similar Reads
Related Tutorials