Given two sorted arrays A[] and B[] consisting of N and M integers respectively, the task is to find the Kth smallest number in the array formed by the product of all possible pairs from array A[] and B[] respectively.
Examples:
Input: A[] = {1, 2, 3}, B[] = {-1, 1}, K = 4 Output: 1 Explanation: The array formed by the product of any two numbers from array A[] and B[] respectively is prod[] = {-3, -2, -1, 1, 2, 3}. Hence, the 4th smallest integer in the prod[] array is 1.
Input: A[] = {-4, -2, 0, 3}, B[] = {1, 10}, K = 7 Output: 3
Approach: The given problem can be solved with the help of Binary Search over all possible values of products. The approach discussed here is very similar to the approach discussed in this article. Below are the steps to follow:
- Create a function check(key), which returns whether the number of elements smaller than the key in the product array is more than K or not. It can be done using the two-pointer technique similar to the algorithm discussed in the article here.
- Perform a binary search over the range [INT_MIN, INT_MAX] to find the smallest number ans such that the number of elements smaller than ans in the product array is at least K.
- After completing the above steps, print the value of ans as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define int long long
bool check( int req, vector< int > posA,
vector< int > posB, vector< int > negA,
vector< int > negB, int K)
{
int cnt = 0;
int first = 0;
int second = negB.size() - 1;
while (first < negA.size()) {
while (second >= 0
&& negA[first]
* negB[second]
<= req)
second--;
cnt += negB.size() - second - 1;
first++;
}
first = 0;
second = posB.size() - 1;
while (first < posA.size()) {
while (second >= 0
&& posA[first]
* posB[second]
> req)
second--;
cnt += second + 1;
first++;
}
first = posA.size() - 1;
second = negB.size() - 1;
while (second >= 0) {
while (first >= 0
&& posA[first]
* negB[second]
<= req)
first--;
cnt += posA.size() - first - 1;
second--;
}
first = negA.size() - 1;
second = posB.size() - 1;
for (; first >= 0; first--) {
while (second >= 0
&& negA[first]
* posB[second]
<= req)
second--;
cnt += posB.size() - second - 1;
}
return (cnt >= K);
}
int kthSmallestProduct(vector< int >& A,
vector< int >& B,
int K)
{
vector< int > posA, negA, posB, negB;
for ( const auto & it : A) {
if (it >= 0)
posA.push_back(it);
else
negA.push_back(it);
}
for ( const auto & it : B)
if (it >= 0)
posB.push_back(it);
else
negB.push_back(it);
int l = LLONG_MIN, r = LLONG_MAX;
int ans;
while (l <= r) {
int mid = (l + r) / 2;
if (check(mid, posA, posB,
negA, negB, K)) {
ans = mid;
r = mid - 1;
}
else {
l = mid + 1;
}
}
return ans;
}
int32_t main()
{
vector< int > A = { -4, -2, 0, 3 };
vector< int > B = { 1, 10 };
int K = 7;
cout << kthSmallestProduct(A, B, K);
return 0;
}
|
Java
import java.util.*;
class GFG{
static boolean check( int req, Vector<Integer> posA,
Vector<Integer> posB, Vector<Integer> negA,
Vector<Integer> negB, int K)
{
int cnt = 0 ;
int first = 0 ;
int second = negB.size() - 1 ;
while (first < negA.size()) {
while (second >= 0
&& negA.elementAt(first)
* negB.elementAt(second)
<= req)
second--;
cnt += negB.size() - second - 1 ;
first++;
}
first = 0 ;
second = posB.size() - 1 ;
while (first < posA.size()) {
while (second >= 0
&& posA.elementAt(first)
* posB.elementAt(second)
> req)
second--;
cnt += second + 1 ;
first++;
}
first = posA.size() - 1 ;
second = negB.size() - 1 ;
while (second >= 0 ) {
while (first >= 0
&& posA.elementAt(first)
* negB.elementAt(second)
<= req)
first--;
cnt += posA.size() - first - 1 ;
second--;
}
first = negA.size() - 1 ;
second = posB.size() - 1 ;
for (; first >= 0 ; first--) {
while (second >= 0
&& negA.elementAt(first)
* posB.elementAt(second)
<= req)
second--;
cnt += posB.size() - second - 1 ;
}
return (cnt >= K);
}
static int kthSmallestProduct( int [] A,
int [] B,
int K)
{
Vector<Integer> posA = new Vector<>();
Vector<Integer> negA = new Vector<>();
Vector<Integer> posB = new Vector<>();
Vector<Integer> negB = new Vector<>();
for ( int it : A) {
if (it >= 0 )
posA.add(it);
else
negA.add(it);
}
for ( int it : B)
if (it >= 0 )
posB.add(it);
else
negB.add(it);
int l = Integer.MIN_VALUE, r = Integer.MAX_VALUE;
int ans= 0 ;
while (l <= r) {
int mid = (l + r) / 2 ;
if (check(mid, posA, posB,
negA, negB, K)) {
ans = mid;
r = mid - 1 ;
}
else {
l = mid + 1 ;
}
}
return ans;
}
public static void main(String[] args)
{
int [] A = { - 4 , - 2 , 0 , 3 };
int [] B = { 1 , 10 };
int K = 7 ;
System.out.print(kthSmallestProduct(A, B, K));
}
}
|
Python3
LLONG_MAX = 9223372036854775807
LLONG_MIN = - 9223372036854775807
def check(req, posA, posB, negA, negB, K):
cnt = 0
first = 0
second = len (negB) - 1
while (first < len (negA)):
while (second > = 0 and negA[first] * negB[second] < = req):
second - = 1
cnt + = len (negB) - second - 1
first + = 1
first = 0
second = len (posB) - 1
while (first < len (posA)):
while (second > = 0 and posA[first] * posB[second] > req):
second - = 1
cnt + = second + 1
first + = 1
first = len (posA) - 1
second = len (negB) - 1
while (second > = 0 ):
while (first > = 0 and posA[first] * negB[second] < = req):
first - = 1
cnt + = len (posA) - first - 1
second - = 1
first = len (negA) - 1
second = len (posB) - 1
for first in range (first, - 1 , - 1 ):
while (second > = 0 and negA[first] * posB[second] < = req):
second - = 1
cnt + = len (posB) - second - 1
return (cnt > = K)
def kthSmallestProduct(A, B, K):
posA = []
negA = []
posB = []
negB = []
for it in A:
if (it > = 0 ):
posA.append(it)
else :
negA.append(it)
for it in B:
if (it > = 0 ):
posB.append(it)
else :
negB.append(it)
l = LLONG_MIN
r = LLONG_MAX
ans = 0
while (l < = r):
mid = (l + r) / / 2
if (check(mid, posA, posB, negA, negB, K)):
ans = mid
r = mid - 1
else :
l = mid + 1
return ans
if __name__ = = "__main__" :
A = [ - 4 , - 2 , 0 , 3 ]
B = [ 1 , 10 ]
K = 7
print (kthSmallestProduct(A, B, K))
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static bool check( int req, List< int > posA, List< int > posB, List< int > negA,
List< int > negB, int K) {
int cnt = 0;
int first = 0;
int second = negB.Count - 1;
while (first < negA.Count) {
while (second >= 0 && negA[first]
* negB[second] <= req)
second--;
cnt += negB.Count - second - 1;
first++;
}
first = 0;
second = posB.Count - 1;
while (first < posA.Count) {
while (second >= 0 && posA[first] * posB[second] > req)
second--;
cnt += second + 1;
first++;
}
first = posA.Count - 1;
second = negB.Count - 1;
while (second >= 0) {
while (first >= 0 && posA[first] * negB[second] <= req)
first--;
cnt += posA.Count - first - 1;
second--;
}
first = negA.Count - 1;
second = posB.Count - 1;
for (; first >= 0; first--) {
while (second >= 0 && negA[first]* posB[second]<= req)
second--;
cnt += posB.Count - second - 1;
}
return (cnt >= K);
}
static int kthSmallestProduct( int [] A, int [] B, int K) {
List< int > posA = new List< int >();
List< int > negA = new List< int >();
List< int > posB = new List< int >();
List< int > negB = new List< int >();
foreach ( int it in A) {
if (it >= 0)
posA.Add(it);
else
negA.Add(it);
}
foreach ( int it in B)
if (it >= 0)
posB.Add(it);
else
negB.Add(it);
int l = int .MinValue, r = int .MaxValue;
int ans = 0;
while (l <= r) {
int mid = (l + r) / 2;
if (check(mid, posA, posB, negA, negB, K)) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
return ans;
}
public static void Main(String[] args) {
int [] A = { -4, -2, 0, 3 };
int [] B = { 1, 10 };
int K = 7;
Console.Write(kthSmallestProduct(A, B, K));
}
}
|
Javascript
<script>
function check(req, posA, posB, negA, negB, K)
{
let cnt = 0;
let first = 0;
let second = negB.length - 1;
while (first < negA.length) {
while (second >= 0 && negA[first] * negB[second] <= req) second--;
cnt += negB.length - second - 1;
first++;
}
first = 0;
second = posB.length - 1;
while (first < posA.length) {
while (second >= 0 && posA[first] * posB[second] > req) second--;
cnt += second + 1;
first++;
}
first = posA.length - 1;
second = negB.length - 1;
while (second >= 0) {
while (first >= 0 && posA[first] * negB[second] <= req) first--;
cnt += posA.length - first - 1;
second--;
}
first = negA.length - 1;
second = posB.length - 1;
for (; first >= 0; first--) {
while (second >= 0 && negA[first] * posB[second] <= req) second--;
cnt += posB.length - second - 1;
}
return cnt >= K;
}
function kthSmallestProduct(A, B, K) {
let posA = [],
negA = [],
posB = [],
negB = [];
for (it of A) {
if (it >= 0) posA.push(it);
else negA.push(it);
}
for (it of B)
if (it >= 0) posB.push(it);
else negB.push(it);
let l = Number.MIN_SAFE_INTEGER,
r = Number.MAX_SAFE_INTEGER;
let ans;
while (l <= r)
{
let mid = (l + r) / 2;
if (check(mid, posA, posB, negA, negB, K)) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
return ans;
}
let A = [-4, -2, 0, 3];
let B = [1, 10];
let K = 7;
document.write(kthSmallestProduct(A, B, K));
</script>
|
Time Complexity: O((N+M)*log 264) or O((N+M)*64) Auxiliary Space: O(N+M)
|