📌  相关文章
📜  从通过将数组中的任何两个数字相乘而形成的排序数组中查找第K个数字

📅  最后修改于: 2021-05-06 07:58:36             🧑  作者: Mango

给定大小为N的数组arr []和整数K ,任务是从乘积数组中找到第K数字。

注意:数组的乘积数组prod []是大小为(N *(N-1))/ 2的排序数组,其中每个元素形成为prod [k] = arr [i] * arr [j] ,其中0≤i

例子:

天真的方法:通过迭代给定数组两次来生成prod []数组,然后对prod []数组进行排序并从数组中找到第K元素。
时间复杂度: O(N 2 * log(N))

高效的方法:可以很容易地确定负,零和正对的数量,因此您可以判断答案是负,零还是正。如果答案是否定的,则可以通过一个一个地选择一个负数和一个正数来测量大于或等于K的线对数,因此可以使用二分查找法获得答案。当答案是肯定的时,答案是完全相同的,但是请考虑两次选择相同的元素,并将其减去将对每对元素精确计数两次。

下面是上述方法的实现:

C++
// C++ implementation to find the
// Kth number in the list formed
// from product of any two numbers
// in the array and sorting them
  
#include 
using namespace std;
  
// Function to find number of pairs
bool check(long long x,
           vector& pos,
           vector& neg, int k)
{
    long long pairs = 0;
  
    int p = neg.size() - 1;
    int nn = neg.size() - 1;
    int pp = pos.size() - 1;
  
    // Negative and Negative
    for (int i = 0; i < neg.size(); i++) {
        while (p >= 0 and neg[i] * neg[p] <= x)
            p--;
  
        // Add Possible Pairs
        pairs += min(nn - p, nn - i);
    }
  
    // Positive and Positive
    p = 0;
    for (int i = pos.size() - 1; i >= 0; i--) {
        while (p < pos.size() and pos[i] * pos[p] <= x)
            p++;
  
        // Add Possible pairs
        pairs += min(p, i);
    }
  
    // Negative and Positive
    p = pos.size() - 1;
    for (int i = neg.size() - 1;
         i >= 0;
         i--) {
        while (p >= 0 and neg[i] * pos[p] <= x)
            p--;
  
        // Add Possible pairs
        pairs += pp - p;
    }
  
    return (pairs >= k);
}
  
// Function to find the kth
// element in the list
long long kth_element(int a[],
                      int n, int k)
{
    vector pos, neg;
  
    // Separate Positive and
    // Negative elements
    for (int i = 0; i < n; i++) {
        if (a[i] >= 0)
            pos.push_back(a[i]);
        else
            neg.push_back(a[i]);
    }
  
    // Sort the Elements
    sort(pos.begin(), pos.end());
    sort(neg.begin(), neg.end());
  
    long long l = -1e18,
              ans = 0, r = 1e18;
  
    // Binary search
    while (l <= r) {
        long long mid = (l + r) >> 1;
        if (check(mid, pos, neg, k)) {
            ans = mid;
            r = mid - 1;
        }
        else
            l = mid + 1;
    }
  
    // Return the required answer
    return ans;
}
  
// Driver code
int main()
{
    int a[] = { -4, -2, 3, 3 }, k = 3;
  
    int n = sizeof(a) / sizeof(a[0]);
  
    // Function call
    cout << kth_element(a, n, k);
  
    return 0;
}


Java
// Java implementation to find the 
// Kth number in the list formed 
// from product of any two numbers 
// in the array and sorting them
import java.util.*; 
  
class GFG 
{
      
    // Function to find number of pairs 
    static boolean check(int x, Vector pos, Vector neg, int k) 
    { 
        int pairs = 0; 
      
        int p = neg.size() - 1; 
        int nn = neg.size() - 1; 
        int pp = pos.size() - 1; 
      
        // Negative and Negative 
        for (int i = 0; i < neg.size(); i++) 
        { 
            while ((p >= 0) && ((int)neg.get(i) * 
                    (int)neg.get(p) <= x)) 
                p--; 
      
            // Add Possible Pairs 
            pairs += Math.min(nn - p, nn - i); 
        } 
      
        // Positive and Positive 
        p = 0; 
        for (int i = pos.size() - 1; i >= 0; i--)
        { 
            while ((p < pos.size()) && ((int)pos.get(i) * 
                    (int)pos.get(p) <= x)) 
                p++; 
      
            // Add Possible pairs 
            pairs += Math.min(p, i); 
        } 
      
        // Negative and Positive 
        p = pos.size() - 1; 
        for (int i = neg.size() - 1; 
            i >= 0; i--) { 
            while ((p >= 0) && ((int)neg.get(i) * 
                    (int)pos.get(p) <= x)) 
                p--; 
      
            // Add Possible pairs 
            pairs += pp - p; 
        } 
      
        return (pairs >= k); 
    } 
      
    // Function to find the kth 
    // element in the list 
    static int kth_element(int a[], int n, int k) 
    { 
        Vector pos = new Vector();
        Vector neg = new Vector();; 
      
        // Separate Positive and 
        // Negative elements 
        for (int i = 0; i < n; i++)
        { 
            if (a[i] >= 0) 
                pos.add(a[i]); 
            else
                neg.add(a[i]); 
        } 
      
        // Sort the Elements 
        //sort(pos.begin(), pos.end()); 
        //sort(neg.begin(), neg.end()); 
        Collections.sort(pos);
        Collections.sort(neg);
      
        int l = (int)-1e8, ans = 0, r = (int)1e8; 
      
        // Binary search 
        while (l <= r)
        { 
            int mid = (l + r) >> 1; 
            if (check(mid, pos, neg, k)) 
            { 
                ans = mid; 
                r = mid - 1; 
            } 
            else
                l = mid + 1; 
        } 
      
        // Return the required answer 
        return ans; 
    } 
      
    // Driver code 
    public static void main (String[] args)
    { 
        int a[] = { -4, -2, 3, 3 }, k = 3; 
        int n = a.length; 
      
        // Function call 
        System.out.println(kth_element(a, n, k)); 
    } 
}
  
// This code is contributed by AnkitRai01


Python3
# Python3 implementation to find the
# Kth number in the list formed
# from product of any two numbers
# in the array and sorting them
  
# Function to find number of pairs
def check(x, pos, neg, k):
    pairs = 0
  
    p = len(neg) - 1
    nn = len(neg) - 1
    pp = len(pos) - 1
  
    # Negative and Negative
    for i in range(len(neg)):
        while (p >= 0 and neg[i] * neg[p] <= x):
            p -= 1
  
        # Add Possible Pairs
        pairs += min(nn - p, nn - i)
  
    # Positive and Positive
    p = 0
    for i in range(len(pos) - 1, -1, -1):
        while (p < len(pos) and pos[i] * pos[p] <= x):
            p += 1
  
        # Add Possible pairs
        pairs += min(p, i)
  
    # Negative and Positive
    p = len(pos) - 1
    for i in range(len(neg) - 1, -1, -1):
        while (p >= 0 and neg[i] * pos[p] <= x):
            p -= 1
  
        # Add Possible pairs
        pairs += pp - p
  
    return (pairs >= k)
  
# Function to find the kth
# element in the list
def kth_element(a, n, k):
    pos, neg = [],[]
  
    # Separate Positive and
    # Negative elements
    for i in range(n):
        if (a[i] >= 0):
            pos.append(a[i])
        else:
            neg.append(a[i])
  
    # Sort the Elements
    pos = sorted(pos)
    neg = sorted(neg)
  
    l = -10**18
    ans = 0
    r = 10**18
  
    # Binary search
    while (l <= r):
        mid = (l + r) >> 1
        if (check(mid, pos, neg, k)):
            ans = mid
            r = mid - 1
        else:
            l = mid + 1
  
    # Return the required answer
    return ans
  
# Driver code
a = [-4, -2, 3, 3]
k = 3
  
n = len(a)
  
# Function call
print(kth_element(a, n, k))
  
# This code is contributed by mohit kumar 29


C#
// C# implementation to find the 
// Kth number in the list formed 
// from product of any two numbers 
// in the array and sorting them
using System;
using System.Collections.Generic;
  
class GFG 
{
      
    // Function to find number of pairs 
    static bool check(int x, List pos, List neg, int k) 
    { 
        int pairs = 0; 
      
        int p = neg.Count - 1; 
        int nn = neg.Count - 1; 
        int pp = pos.Count - 1; 
      
        // Negative and Negative 
        for (int i = 0; i < neg.Count; i++) 
        { 
            while ((p >= 0) && ((int)neg[i] * 
                    (int)neg[p] <= x)) 
                p--; 
      
            // Add Possible Pairs 
            pairs += Math.Min(nn - p, nn - i); 
        } 
      
        // Positive and Positive 
        p = 0; 
        for (int i = pos.Count - 1; i >= 0; i--)
        { 
            while ((p < pos.Count) && ((int)pos[i] * 
                    (int)pos[p] <= x)) 
                p++; 
      
            // Add Possible pairs 
            pairs += Math.Min(p, i); 
        } 
      
        // Negative and Positive 
        p = pos.Count - 1; 
        for (int i = neg.Count - 1; i >= 0; i--) 
        { 
            while ((p >= 0) && ((int)neg[i] * 
                    (int)pos[p] <= x)) 
                p--; 
      
            // Add Possible pairs 
            pairs += pp - p; 
        } 
      
        return (pairs >= k); 
    } 
      
    // Function to find the kth 
    // element in the list 
    static int kth_element(int []a, int n, int k) 
    { 
        List pos = new List();
        List neg = new List();; 
      
        // Separate Positive and 
        // Negative elements 
        for (int i = 0; i < n; i++)
        { 
            if (a[i] >= 0) 
                pos.Add(a[i]); 
            else
                neg.Add(a[i]); 
        } 
      
        // Sort the Elements 
        //sort(pos.begin(), pos.end()); 
        //sort(neg.begin(), neg.end()); 
        pos.Sort();
        neg.Sort();
      
        int l = (int)-1e8, ans = 0, r = (int)1e8; 
      
        // Binary search 
        while (l <= r)
        { 
            int mid = (l + r) >> 1; 
            if (check(mid, pos, neg, k)) 
            { 
                ans = mid; 
                r = mid - 1; 
            } 
            else
                l = mid + 1; 
        } 
      
        // Return the required answer 
        return ans; 
    } 
      
    // Driver code 
    public static void Main(String[] args)
    { 
        int []a = { -4, -2, 3, 3 };
        int k = 3; 
        int n = a.Length; 
      
        // Function call 
        Console.WriteLine(kth_element(a, n, k)); 
    } 
}
  
// This code is contributed by 29AjayKumar


输出:
-6