Kth largest pairwise product possible from given two Arrays
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> |
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. |
3
Time Complexity: O(M*Log(M) + K*Log(N))
Auxiliary Space: O(N)
Please Login to comment...