📜  使用给定的比较器计算对的数量

📅  最后修改于: 2021-09-03 04:05:13             🧑  作者: Mango

给定一个数组arr[] ,任务是使用任何自定义比较器计算每个元素右侧的对 (arr[i], arr[j]) 的数量。

比较器可以是任何类型,下面给出了其中的一些 –

arr[i] > arr[j],    where i < j
arr[i] < arr[j],    where i  2 * arr[j], where i < j

例子:

天真的解决方案:迭代每对元素,使得i < j并检查每对自定义比较器是否为真。如果是,则增加计数。
时间复杂度: O(N 2 )

高效的方法:这个想法是自定义归并排序,在合并两个子数组时计算这样的对。每个数组都有两种类型的计数——

  • 阵列间对:存在于左子阵列本身中的对。
  • 阵列内对:对存在于右子阵列中的那些对。

对于左子数组,可以从下到上递归计算计数,而主要任务是计算数组内对。

因此,此类对的总数可以定义为 –

Total Pairs = Inter-Array pairs in Left Sub-array +
      Inter-Array pairs in Right Sub-array +
      Intra-Array pairs from left to right sub-array 

下面是从左子阵列到右子阵列的阵列内阵列对的图示——

  • 基本情况:这个问题的基本情况是两个子数组中只有一个元素,我们想检查数组内对。然后,检查这两个元素是否形成这样的一对,然后增加计数并将较小的元素放在其位置。
if start1 == end1 and start2 == end2:
    if compare(arr, start1, start2):
        c += 1
  • Recursive Case:这个问题根据比较器的函数可以分为三类——
    1. 当对之间运算符是大于或等于。
    2. 当对之间运算符是小于或等于。
    3. 当对之间运算符等于。

因此,对于这些对,可以单独计算所有这三种情况。

  • 情况 1:如果大于或等于,如果我们找到任何这样的对,则该子数组右侧的所有元素也将与当前元素形成对。因此,这些对的计数增加了左子数组中剩余元素的数量。
if compare(arr, start1, start2):
    count += end1 - start1 + 1
  • 情况 2:在小于或等于的情况下,如果我们找到任何这样的对,则该子数组右侧的所有元素也将与当前元素形成对。因此,此类对的计数增加了右侧子数组中左侧的元素数。
if compare(arr, start1, start2):
    count += end2 - start2 + 1
  • 情况 3:如果等于,如果我们找到任何这样的对,那么我们会在 while 循环的帮助下尝试在左子数组中找到所有可能的这样的对。在每个这样的可能对中,将计数加 1。
if compare(arr, start1, start2):
    while compare(arr, start1, start2):
        count += 1
        start1 += 1
  • 最后,像在合并排序中那样合并两个子数组。

下面是上述方法的实现:

C++
// C++ implementation to find the
// elements on the right with the given
// custom comparator
 
#include 
 
using namespace std;
 
// comparator to check
// if two elements are equal
bool compare(int arr[], int s1, int s2){
    if (arr[s1] > arr[s2]){
        return true;
    }
    else{
        return false;
    }
}
 
// Function to find the Intra-Array
// Count in the two subarrays
int findIntraArrayCount(int arr[], int s1,
       int e1, int s2, int e2, int g){
            
    // Base Case
    if (s1 == e1 && s2 == e2){
        int c = 0;
        if (compare(arr, s1, s2)){
            c += 1;
        }
        if (arr[s1] > arr[s2]){
            int temp = arr[s1];
            arr[s1] = arr[s2];
            arr[s2] = temp;
        }
        return c;
    }
     
    // Variable for keeping
    // the count of the pair
    int c = 0;
    int s = s1, e = e2, s3 = s1;
    int e3 = e1, s4 = s2, e4 = e2;
     
    while (s1 <= e1 && s2 <= e2){
         
        // Condition when we have to use the
        // Greater than comparator
        if (g == 1){
            if (compare(arr, s1, s2)){
                c += e1 - s1 + 1;
                s2 += 1;
            }
            else{
                s1 += 1;
            }
        }
         
        // Condition when we have to use the
        // Less than comparator
        else if (g == 0){
            if (compare(arr, s1, s2)){
                c += e2 - s2 + 1;
                s1 += 1;
            }
            else {
                s2 += 1;
            }
        }
         
        // Condition when we have to use the
        // Equal to Comparator
        else if (g == -1){
            if (compare(arr, s1, s2)){
                int c1 = 0;
                while (s1 <= e1 &&
                       compare(arr, s1, s2)){
                    c1 += 1;
                    s1 += 1;
                }
                s1 -= 1;
                int c2 = 0;
                while (s2 <= e2 &&
                       compare(arr, s1, s2)){
                    c2 += 1;
                    s2 += 1;
                }
                c += c1 * c2;
            }
            else {
                if (arr[s1] > arr[s2]){
                    s2 += 1;
                }
                else{
                    s1 += 1;
                }
            }
        }
    }
    s1 = s3; e1 = e3;
    s2 = s4; e2 = e4;
     
    // Array to store
    // the sorted subarray
    vector aux;
     
    // Merge the two subarrays
    while (s1 <= e1 && s2 <= e2){
        if (arr[s1] <= arr[s2]){
            aux.push_back(arr[s1]);
            s1 += 1;
        }
        else{
            aux.push_back(arr[s2]);
            s2 += 1;
        }
    }
     
    // Copy subarray 1 elements
    while (s1 <= e1){
        aux.push_back(arr[s1]);
        s1 += 1;
    }
     
    // Copy subarray 2 elements
    while (s2 <= e2){
        aux.push_back(arr[s2]);
        s2 += 1;
    }
     
    // Update the original array
    for (int i = s; i <= e; i++){
        arr[i] = aux[i-s];
    }
    return c;
}
 
// Function to find such pairs with
// any custom comparator function
int findElementsOnRight(int arr[], int s,
                           int e, int g){
    if (s >= e){
        return 0;
    }
    int mid = (s+e)/2;
     
    // Recursive call for inter-array
    // count of pairs in left subarrays
    int c1 = findElementsOnRight(
                      arr, s, mid, g);
     
    // Recursive call for inter-array
    // count of pairs in right sub-arrays
    int c2 = findElementsOnRight(
                   arr, mid + 1, e, g);
     
    // Call for intra-array pairs
    int c3 = findIntraArrayCount(
              arr, s, mid, mid+1, e, g);
     
    return c1 + c2 + c3;
}
 
 
// Driver code
int main()
{
    int arr[] = {4, 3, 2, 1};
    int g = 1;
    cout << findElementsOnRight(arr, 0, 3, g);
    return 0;
}


Java
// Java implementation to find the
// elements on the right with the given
// custom comparator
 
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG {
     
    // comparator to check
    // if two elements are equal
    public static boolean compare(
          int[] arr, int s1, int s2){
        if (arr[s1] > arr[s2]){
            return true;
        }
        else{
            return false;
        }
    }
     
    // Function to find the Intra-Array
    // Count in the two subarrays
    public static int findIntraArrayCount(
        int[] arr, int s1, int e1, int s2,
                           int e2, int g){
                                
        // Base Case
        if (s1 == e1 && s2 == e2){
            int c = 0;
            if (compare(arr, s1, s2)){
                c += 1;
            }
            if (arr[s1] > arr[s2]){
                int temp = arr[s1];
                arr[s1] = arr[s2];
                arr[s2] = temp;
            }
            return c;
        }
         
        // Variable for keeping
        // the count of the pair
        int c = 0;
        int s = s1, e = e2, s3 = s1;
        int e3 = e1, s4 = s2, e4 = e2;
         
        while (s1 <= e1 && s2 <= e2){
             
            // Condition when we have to use the
            // Greater than comparator
            if (g == 1){
                if (compare(arr, s1, s2)){
                    c += e1 - s1 + 1;
                    s2 += 1;
                }
                else{
                    s1 += 1;
                }
            }
             
            // Condition when we have to use the
            // Equal to Comparator
            else if (g == 0){
                if (compare(arr, s1, s2)){
                    c += e2 - s2 + 1;
                    s1 += 1;
                }
                else {
                    s2 += 1;
                }
            }
             
            // Condition when we have to use the
            // Equal to Comparator
            else if (g == -1){
                if (compare(arr, s1, s2)){
                    int c1 = 0;
                    while (s1 <= e1 &&
                         compare(arr, s1, s2)){
                        c1 += 1;
                        s1 += 1;
                    }
                    s1 -= 1;
                    int c2 = 0;
                    while (s2 <= e2 &&
                          compare(arr, s1, s2)){
                        c2 += 1;
                        s2 += 1;
                    }
                    c += c1 * c2;
                }
                else {
                    if (arr[s1] > arr[s2]){
                        s2 += 1;
                    }
                    else{
                        s1 += 1;
                    }
                }
            }
        }
        s1 = s3; e1 = e3;
        s2 = s4; e2 = e4;
         
        // Array to store
        // the sorted subarray
        ArrayList aux =
                     new ArrayList<>();
                      
        // Merge the two subarrays
        while (s1 <= e1 && s2 <= e2){
            if (arr[s1] <= arr[s2]){
                aux.add(arr[s1]);
                s1 += 1;
            }
            else{
                aux.add(arr[s2]);
                s2 += 1;
            }
        }
         
        // Copy subarray 1 elements
        while (s1 <= e1){
            aux.add(arr[s1]);
            s1 += 1;
        }
         
        // Copy subarray 2 elements
        while (s2 <= e2){
            aux.add(arr[s2]);
            s2 += 1;
        }
         
        // Update the original array
        for (int i = s; i <= e; i++){
            arr[i] = aux.get(i-s);
        }
        return c;
    }
     
    // Function to find such pairs with
    // any custom comparator function
    public static int findElementsOnRight(
        int[] arr, int s, int e, int g){
        if (s >= e){
            return 0;
        }
        int mid = (s+e)/2;
         
        // Recursive call for inter-array
        // count of pairs in left subarrays
        int c1 = findElementsOnRight(arr, s,
                                     mid, g);
         
        // Recursive call for inter-array
        // count of pairs in right sub-arrays
        int c2 = findElementsOnRight(arr, mid + 1,
                                         e, g);
         
        // Call for intra-array pairs
        int c3 = findIntraArrayCount(arr, s,
                            mid, mid+1, e, g);
         
        return c1 + c2 + c3;                                  
    }
     
    // Driver code
    public static void main (String[] args) {
        int[] arr = {4, 3, 2, 1};
        int g = 1;
        System.out.println(
            findElementsOnRight(arr, 0, 3, g));
    }
}


Python3
# Python3 implementation to find the
# elements on the right with the given
# custom comparator
 
import random, math
from copy import deepcopy as dc
 
# comparator to check
# if two elements are equal
def compare(arr, s1, s2):
    if arr[s1] > arr[s2]:
        return True
    else:
        return False
 
 
# Function to find the Intra-Array
# Count in the two subarrays
def findIntraArrayCount(arr, s1, \
                e1, s2, e2, g):
     
    # Base Case
    if s1 == e1 and s2 == e2:
        c = 0
        if compare(arr, s1, s2):
            c += 1
        if arr[s1] > arr[s2]:
            arr[s1], arr[s2] = arr[s2], arr[s1]
        return c
 
 
    # Variable for keeping
    # the count of the pair
    c = 0
     
    # Total subarray length
    s = dc(s1); e = dc(e2)
     
    # length of subarray 1
    s3 = dc(s1); e3 = dc(e1)
     
    # length of subarray 2
    s4 = dc(s2); e4 = dc(e2)
     
    while s1 <= e1 and s2 <= e2:
 
 
        # Condition when we have to use the
        # Greater than comparator
        if g == 1:
            if compare(arr, s1, s2):
                c += e1 - s1 + 1
                s2 += 1
            else:
                s1 += 1
 
        # Condition when we have to use the
        # Less than comparator
        elif g == 0:
            if compare(arr, s1, s2):
                c += e2 - s2 + 1
                s1 += 1
            else:
                s2 += 1
                 
        # Condition when we have to use the
        # Equal to Comparator
        elif g == -1:
            if compare(arr, s1, s2):
                c1 = 0
                while s1 <= e1 and\
                   compare(arr, s1, s2):
                    c1 += 1
                    s1 += 1
                s1 -= 1
                c2 = 0
                while s2 <= e2 and\
                    compare(arr, s1, s2):
                    c2 += 1
                    s2 += 1
                c += c1 * c2
            else:
                if arr[s1] > arr[s2]:
                    s2 += 1
                else:
                    s1 += 1
 
    s1 = dc(s3); e1 = dc(e3)
     
    s2 = dc(s4); e2 = dc(e4)
     
    # Array to store the sorted subarray
    aux = []
     
     
    # Merge the two subarrays
    while s1 <= e1 and s2 <= e2:
        if arr[s1] <= arr[s2]:
            aux.append(arr[s1])
            s1 += 1
        else:
            aux.append(arr[s2])
            s2 += 1
     
    # Copy subarray 1 elements
    while s1 <= e1:
        aux.append(arr[s1])
        s1 += 1
         
     
    # Copy subarray 2 elements
    while s2 <= e2:
        aux.append(arr[s2])
        s2 += 1
         
     
    # Update the original array
    for i in range(s, e + 1):
        arr[i] = aux[i-s]
    return c
 
 
 
# Function to find such pairs with
# any custom comparator function
def findElementsOnRight(arr, s, e, g):
    if s >= e:
        return 0
    mid = (s + e)//2
     
    # Recursive call for inter-array
    # count of pairs in left subarrays
    c1 = findElementsOnRight(arr, s, \
                            mid, g)
     
    # Recursive call for inter-array
    # count of pairs in right sub-arrays
    c2 = findElementsOnRight(arr, mid + 1, \
                                e, g)
     
    # Call for intra-array pairs
    c3 = findIntraArrayCount(arr, s, mid, \
                            mid + 1, e, g)
    return c1 + c2 + c3
 
 
 
 
# Driver Code
if __name__ == "__main__":
    arr = [4, 3, 2, 1]
    g = 1
    out = findElementsOnRight(arr, 0, \
                        len(arr)-1, g)
    print(out)


C#
// C# implementation to find the 
// elements on the right with the
// given custom comparator 
using System;
using System.Collections.Generic;
 
class GFG{
     
// comparator to check 
// if two elements are equal 
public static bool compare(int[] arr, int s1,
                                      int s2)
{
    if (arr[s1] > arr[s2])
    {
        return true;
    }
    else
    {
        return false;
    }
}
   
// Function to find the Intra-Array 
// Count in the two subarrays 
public static int findIntraArrayCount(int[] arr, int s1,
                                      int e1, int s2, 
                                      int e2, int g)
{
     
    // Base Case
    if (s1 == e1 && s2 == e2)
    {
        int cc = 0;
        if (compare(arr, s1, s2))
        {
            cc += 1;
        }
        if (arr[s1] > arr[s2])
        {
            int temp = arr[s1];
            arr[s1] = arr[s2];
            arr[s2] = temp;
        }
        return cc;
    }
       
    // Variable for keeping 
    // the count of the pair
    int c = 0;
    int s = s1, e = e2, s3 = s1;
    int e3 = e1, s4 = s2, e4 = e2;
       
    while (s1 <= e1 && s2 <= e2)
    {
         
        // Condition when we have to use the 
        // Greater than comparator
        if (g == 1)
        {
            if (compare(arr, s1, s2))
            {
                c += e1 - s1 + 1;
                s2 += 1;
            }
            else
            {
                s1 += 1;
            }
        }
           
        // Condition when we have to use the 
        // Equal to Comparator 
        else if (g == 0)
        {
            if (compare(arr, s1, s2))
            {
                c += e2 - s2 + 1;
                s1 += 1;
            }
            else
            {
                s2 += 1;
            }
        }
           
        // Condition when we have to use the 
        // Equal to Comparator 
        else if (g == -1)
        {
            if (compare(arr, s1, s2))
            {
                int c1 = 0;
                while (s1 <= e1 && 
                       compare(arr, s1, s2))
                {
                    c1 += 1;
                    s1 += 1;
                }
                s1 -= 1;
                int c2 = 0;
                while (s2 <= e2 && 
                       compare(arr, s1, s2))
                {
                    c2 += 1;
                    s2 += 1;
                }
                c += c1 * c2;
            }
            else
            {
                if (arr[s1] > arr[s2])
                {
                    s2 += 1;
                }
                else
                {
                    s1 += 1;
                }
            }
        }
    }
    s1 = s3; e1 = e3;
    s2 = s4; e2 = e4;
       
    // Array to store 
    // the sorted subarray
    List aux = new List();
                    
    // Merge the two subarrays
    while (s1 <= e1 && s2 <= e2)
    {
        if (arr[s1] <= arr[s2])
        {
            aux.Add(arr[s1]);
            s1 += 1;
        }
        else
        {
            aux.Add(arr[s2]);
            s2 += 1;
        }
    }
       
    // Copy subarray 1 elements 
    while (s1 <= e1)
    {
        aux.Add(arr[s1]);
        s1 += 1;
    }
       
    // Copy subarray 2 elements
    while (s2 <= e2)
    {
        aux.Add(arr[s2]);
        s2 += 1;
    }
       
    // Update the original array
    for(int i = s; i <= e; i++)
    {
        arr[i] = aux[i-s];
    }
    return c;
}
   
// Function to find such pairs with 
// any custom comparator function 
public static int findElementsOnRight(int[] arr, int s,
                                      int e, int g)
{
    if (s >= e)
    {
        return 0;
    }
    int mid = (s + e) / 2;
       
    // Recursive call for inter-array 
    // count of pairs in left subarrays
    int c1 = findElementsOnRight(arr, s, 
                                 mid, g);
       
    // Recursive call for inter-array 
    // count of pairs in right sub-arrays 
    int c2 = findElementsOnRight(arr, mid + 1, 
                                   e, g);
       
    // Call for intra-array pairs 
    int c3 = findIntraArrayCount(arr, s, mid,
                                 mid + 1, e, g);
       
    return c1 + c2 + c3;                                   
}
 
// Driver code
static public void Main()
{
    int[] arr = { 4, 3, 2, 1 };
    int g = 1;
     
    Console.WriteLine(findElementsOnRight(
        arr, 0, 3, g));
}
}
 
// This code is contributed by offbeat


Javascript


输出:
6

时间复杂度:上述方法需要 O(N*logN) 时间。
辅助空间: O(N)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live