📌  相关文章
📜  由两个数组中任意两个元素的乘积形成的数组中第 K 个最小的数

📅  最后修改于: 2022-05-13 01:56:09.285000             🧑  作者: Mango

由两个数组中任意两个元素的乘积形成的数组中第 K 个最小的数

给定两个分别由NM个整数组成的已排序数组A[]B[] ,任务是在由数组A[]B[]中所有可能对的乘积形成的数组中找到第K最小的数.

例子:

方法:给定的问题可以在产品的所有可能值的二进制搜索的帮助下解决。这里讨论的方法与本文讨论的方法非常相似。以下是要遵循的步骤:

  • 创建一个函数check(key) ,返回 product 数组中小于 key 的元素个数是否大于K。可以使用类似于本文中讨论的算法的两指针技术来完成。
  • [INT_MIN, INT_MAX]范围内执行二进制搜索以找到最小的数字ans使得 产品数组中小于ans的元素数量至少为K
  • 完成上述步骤后,打印ans的值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
#define int long long
 
// Function to check if count of elements
// greater than req in product array are
// more than K or not
bool check(int req, vector posA,
           vector posB, vector negA,
           vector negB, int K)
{
    // Stores the count of numbers less
    // than or equal to req
    int cnt = 0;
 
    // Case with both elements of A[] and
    // B[] are negative
    int first = 0;
    int second = negB.size() - 1;
 
    // Count number of pairs formed from
    // array A[] and B[] with both elements
    // negative and there product <= req
    while (first < negA.size()) {
        while (second >= 0
               && negA[first]
                          * negB[second]
                      <= req)
            second--;
 
        // Update cnt
        cnt += negB.size() - second - 1;
        first++;
    }
 
    // Case with both elements of A[] and
    // B[] are positive
    first = 0;
    second = posB.size() - 1;
 
    // Count number of pairs formed from
    // array A[] and B[] with both elements
    // positive and there product <= req
    while (first < posA.size()) {
        while (second >= 0
               && posA[first]
                          * posB[second]
                      > req)
            second--;
 
        // Update cnt
        cnt += second + 1;
        first++;
    }
 
    // Case with elements of A[] and B[]
    // as positive and negative respectively
    first = posA.size() - 1;
    second = negB.size() - 1;
 
    // Count number of pairs formed from
    // +ve integers of A[] and -ve integer
    // of array B[] product <= req
    while (second >= 0) {
        while (first >= 0
               && posA[first]
                          * negB[second]
                      <= req)
            first--;
 
        // Update cnt
        cnt += posA.size() - first - 1;
        second--;
    }
 
    // Case with elements of A[] and B[]
    // as negative and positive respectively
    first = negA.size() - 1;
    second = posB.size() - 1;
 
    // Count number of pairs formed from
    // -ve and +ve integers from A[] and
    // B[] with product <= req
    for (; first >= 0; first--) {
        while (second >= 0
               && negA[first]
                          * posB[second]
                      <= req)
            second--;
 
        // Update cnt
        cnt += posB.size() - second - 1;
    }
 
    // Return Answer
    return (cnt >= K);
}
 
// Function to find the Kth smallest
// number in array formed by product of
// any two elements from A[] and B[]
int kthSmallestProduct(vector& A,
                       vector& B,
                       int K)
{
    vector posA, negA, posB, negB;
 
    // Loop to iterate array A[]
    for (const auto& it : A) {
        if (it >= 0)
            posA.push_back(it);
        else
            negA.push_back(it);
    }
 
    // Loop to iterate array B[]
    for (const auto& it : B)
        if (it >= 0)
            posB.push_back(it);
        else
            negB.push_back(it);
 
    // Stores the lower and upper bounds
    // of the binary search
    int l = LLONG_MIN, r = LLONG_MAX;
 
    // Stores the final answer
    int ans;
 
    // Find the kth smallest integer
    // using binary search
    while (l <= r) {
 
        // Stores the mid
        int mid = (l + r) / 2;
 
        // If the number of elements
        // greater than mid in product
        // array are more than K
        if (check(mid, posA, posB,
                  negA, negB, K)) {
            ans = mid;
            r = mid - 1;
        }
        else {
            l = mid + 1;
        }
    }
 
    // Return answer
    return ans;
}
 
// Driver Code
int32_t main()
{
    vector A = { -4, -2, 0, 3 };
    vector B = { 1, 10 };
    int K = 7;
 
    cout << kthSmallestProduct(A, B, K);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
 
// Function to check if count of elements
// greater than req in product array are
// more than K or not
static boolean check(int req, Vector posA,
           Vector posB, Vector negA,
           Vector negB, int K)
{
   
    // Stores the count of numbers less
    // than or equal to req
    int cnt = 0;
 
    // Case with both elements of A[] and
    // B[] are negative
    int first = 0;
    int second = negB.size() - 1;
 
    // Count number of pairs formed from
    // array A[] and B[] with both elements
    // negative and there product <= req
    while (first < negA.size()) {
        while (second >= 0
               && negA.elementAt(first)
                          * negB.elementAt(second)
                      <= req)
            second--;
 
        // Update cnt
        cnt += negB.size() - second - 1;
        first++;
    }
 
    // Case with both elements of A[] and
    // B[] are positive
    first = 0;
    second = posB.size() - 1;
 
    // Count number of pairs formed from
    // array A[] and B[] with both elements
    // positive and there product <= req
    while (first < posA.size()) {
        while (second >= 0
               && posA.elementAt(first)
                          * posB.elementAt(second)
                      > req)
            second--;
 
        // Update cnt
        cnt += second + 1;
        first++;
    }
 
    // Case with elements of A[] and B[]
    // as positive and negative respectively
    first = posA.size() - 1;
    second = negB.size() - 1;
 
    // Count number of pairs formed from
    // +ve integers of A[] and -ve integer
    // of array B[] product <= req
    while (second >= 0) {
        while (first >= 0
               && posA.elementAt(first)
                          * negB.elementAt(second)
                      <= req)
            first--;
 
        // Update cnt
        cnt += posA.size() - first - 1;
        second--;
    }
 
    // Case with elements of A[] and B[]
    // as negative and positive respectively
    first = negA.size() - 1;
    second = posB.size() - 1;
 
    // Count number of pairs formed from
    // -ve and +ve integers from A[] and
    // B[] with product <= req
    for (; first >= 0; first--) {
        while (second >= 0
               && negA.elementAt(first)
                          * posB.elementAt(second)
                      <= req)
            second--;
 
        // Update cnt
        cnt += posB.size() - second - 1;
    }
 
    // Return Answer
    return (cnt >= K);
}
 
// Function to find the Kth smallest
// number in array formed by product of
// any two elements from A[] and B[]
static int kthSmallestProduct(int[] A,
                       int[] B,
                       int K)
{
    Vector posA = new Vector<>();
    Vector negA = new Vector<>();
    Vector posB = new Vector<>();
    Vector negB = new Vector<>();
    // Loop to iterate array A[]
    for (int  it : A) {
        if (it >= 0)
            posA.add(it);
        else
            negA.add(it);
    }
 
    // Loop to iterate array B[]
    for (int it : B)
        if (it >= 0)
            posB.add(it);
        else
            negB.add(it);
 
    // Stores the lower and upper bounds
    // of the binary search
    int l = Integer.MIN_VALUE, r = Integer.MAX_VALUE;
 
    // Stores the final answer
    int ans=0;
 
    // Find the kth smallest integer
    // using binary search
    while (l <= r) {
 
        // Stores the mid
        int mid = (l + r) / 2;
 
        // If the number of elements
        // greater than mid in product
        // array are more than K
        if (check(mid, posA, posB,
                  negA, negB, K)) {
            ans = mid;
            r = mid - 1;
        }
        else {
            l = mid + 1;
        }
    }
 
    // Return answer
    return ans;
}
 
// Driver Code
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));
 
}
}
 
// This code is contributed by gauravrajput1


Python3
# python program for the above approach
LLONG_MAX = 9223372036854775807
LLONG_MIN = -9223372036854775807
 
# Function to check if count of elements
# greater than req in product array are
# more than K or not
def check(req, posA, posB, negA, negB, K):
 
    # Stores the count of numbers less
    # than or equal to req
    cnt = 0
 
    # Case with both elements of A[] and
    # B[] are negative
    first = 0
    second = len(negB) - 1
 
    # Count number of pairs formed from
    # array A[] and B[] with both elements
    # negative and there product <= req
    while (first < len(negA)):
        while (second >= 0 and negA[first] * negB[second] <= req):
            second -= 1
 
        # Update cnt
        cnt += len(negB) - second - 1
        first += 1
 
    # Case with both elements of A[] and
    # B[] are positive
    first = 0
    second = len(posB) - 1
 
    # Count number of pairs formed from
    # array A[] and B[] with both elements
    # positive and there product <= req
    while (first < len(posA)):
        while (second >= 0 and posA[first] * posB[second] > req):
            second -= 1
 
        # Update cnt
        cnt += second + 1
        first += 1
 
    # Case with elements of A[] and B[]
    # as positive and negative respectively
    first = len(posA) - 1
    second = len(negB) - 1
 
    # Count number of pairs formed from
    # +ve integers of A[] and -ve integer
    # of array B[] product <= req
    while (second >= 0):
        while (first >= 0 and posA[first] * negB[second] <= req):
            first -= 1
 
        # Update cnt
        cnt += len(posA) - first - 1
        second -= 1
 
    # Case with elements of A[] and B[]
    # as negative and positive respectively
    first = len(negA) - 1
    second = len(posB) - 1
 
    # Count number of pairs formed from
    # -ve and +ve integers from A[] and
    # B[] with product <= req
    for first in range(first, -1, -1):
        while (second >= 0 and negA[first] * posB[second] <= req):
            second -= 1
 
        # Update cnt
        cnt += len(posB) - second - 1
 
    # Return Answer
    return (cnt >= K)
 
 
# Function to find the Kth smallest
# number in array formed by product of
# any two elements from A[] and B[]
def kthSmallestProduct(A, B, K):
 
    posA = []
    negA = []
    posB = []
    negB = []
 
    # Loop to iterate array A[]
    for it in A:
        if (it >= 0):
            posA.append(it)
        else:
            negA.append(it)
 
        # Loop to iterate array B[]
    for it in B:
        if (it >= 0):
            posB.append(it)
        else:
            negB.append(it)
 
        # Stores the lower and upper bounds
        # of the binary search
    l = LLONG_MIN
    r = LLONG_MAX
 
    # Stores the final answer
    ans = 0
 
    # Find the kth smallest integer
    # using binary search
    while (l <= r):
 
        # Stores the mid
        mid = (l + r) // 2
 
        # If the number of elements
        # greater than mid in product
        # array are more than K
        if (check(mid, posA, posB, negA, negB, K)):
            ans = mid
            r = mid - 1
        else:
            l = mid + 1
 
        # Return answer
    return ans
 
 
# Driver Code
if __name__ == "__main__":
 
    A = [-4, -2, 0, 3]
    B = [1, 10]
    K = 7
 
    print(kthSmallestProduct(A, B, K))
 
    # This code is contributed by rakeshsahni


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
 
    // Function to check if count of elements
    // greater than req in product array are
    // more than K or not
    static bool check(int req, List posA, List posB, List negA,
            List negB, int K) {
 
        // Stores the count of numbers less
        // than or equal to req
        int cnt = 0;
 
        // Case with both elements of []A and
        // []B are negative
        int first = 0;
        int second = negB.Count - 1;
 
        // Count number of pairs formed from
        // array []A and []B with both elements
        // negative and there product <= req
        while (first < negA.Count) {
            while (second >= 0 && negA[first]
                          * negB[second] <= req)
                second--;
 
            // Update cnt
            cnt += negB.Count - second - 1;
            first++;
        }
 
        // Case with both elements of []A and
        // []B are positive
        first = 0;
        second = posB.Count - 1;
 
        // Count number of pairs formed from
        // array []A and []B with both elements
        // positive and there product <= req
        while (first < posA.Count) {
            while (second >= 0 && posA[first] * posB[second] > req)
                second--;
 
            // Update cnt
            cnt += second + 1;
            first++;
        }
 
        // Case with elements of []A and []B
        // as positive and negative respectively
        first = posA.Count - 1;
        second = negB.Count - 1;
 
        // Count number of pairs formed from
        // +ve integers of []A and -ve integer
        // of array []B product <= req
        while (second >= 0) {
            while (first >= 0 && posA[first] * negB[second] <= req)
                first--;
 
            // Update cnt
            cnt += posA.Count - first - 1;
            second--;
        }
 
        // Case with elements of []A and []B
        // as negative and positive respectively
        first = negA.Count - 1;
        second = posB.Count - 1;
 
        // Count number of pairs formed from
        // -ve and +ve integers from []A and
        // []B with product <= req
        for (; first >= 0; first--) {
            while (second >= 0 && negA[first]* posB[second]<= req)
                second--;
 
            // Update cnt
            cnt += posB.Count - second - 1;
        }
 
        // Return Answer
        return (cnt >= K);
    }
 
    // Function to find the Kth smallest
    // number in array formed by product of
    // any two elements from []A and []B
    static int kthSmallestProduct(int[] A, int[] B, int K) {
        List posA = new List();
        List negA = new List();
        List posB = new List();
        List negB = new List();
        // Loop to iterate array []A
        foreach (int it in A) {
            if (it >= 0)
                posA.Add(it);
            else
                negA.Add(it);
        }
 
        // Loop to iterate array []B
        foreach (int it in B)
            if (it >= 0)
                posB.Add(it);
            else
                negB.Add(it);
 
        // Stores the lower and upper bounds
        // of the binary search
        int l = int.MinValue, r = int.MaxValue;
 
        // Stores the readonly answer
        int ans = 0;
 
        // Find the kth smallest integer
        // using binary search
        while (l <= r) {
 
            // Stores the mid
            int mid = (l + r) / 2;
 
            // If the number of elements
            // greater than mid in product
            // array are more than K
            if (check(mid, posA, posB, negA, negB, K)) {
                ans = mid;
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
 
        // Return answer
        return ans;
    }
 
    // Driver Code
    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));
 
    }
}
 
// This code is contributed by gauravrajput1


Javascript


输出:
3

时间复杂度: O((N+M)*log 2 64 ) 或 O((N+M)*64)
辅助空间: O(N+M)