Home > Enterprise >  Find no. of Comparisons such that A[i] A[j]> B[i] B[j] where i<j
Find no. of Comparisons such that A[i] A[j]> B[i] B[j] where i<j

Time:01-06

I want to write an algorithm to count no. of comparisons such that A[i] A[j]> B[i] B[j] where i<j in as less time as possible.

I know the Brute-Force approach for this, but it take O(n^2) time while I need to solve it in less time. I have also explored the approach based on Merge Sort, but it doesn't seem to work properly

#include <algorithm> // for sort

int comparisons = 0;

// sort arrays A and B in ascending order
std::sort(A.begin(), A.end());
std::sort(B.begin(), B.end());

for (int i = 0; i < A.size(); i  ) {
    for (int j = i 1; j < A.size(); j  ) {
        if (A[i]   A[j] > B[i]   B[j]) {
            comparisons  ;
        }
    }
}

CodePudding user response:

Rewriting the condition as A[i] - B[i] > - (A[j] - B[j]), you turn the problem to the detection of C[i] > - C[j]. After sorting, you easily solve this as a merge operation between the array C and the array -C inverted. (There is no need to invert explicitly, just adjust the indexes.) This is done in time Θ(N Log N), unless a faster sort is possible.

CodePudding user response:

As mentioned in a comment, the relation corresponds to C[i] > -C[j], where C[i] = A[i] - B[i].

The count is easy after the sorting of C.

We just have to pay attention to exclude the cases i == j, and to take into account that a direct summation doubles the number of cases.

Complexity is dominated by the sorting: O(n logn).

#include <iostream>
#include <vector>
#include <algorithm>

int n_compar_bf (const std::vector<int>& A, const std::vector<int>& B) {
    int comparisons = 0;
    for (int i = 0; i < A.size(); i  ) {
        for (int j = i 1; j < A.size(); j  ) {
            if (A[i]   A[j] > B[i]   B[j]) {
                comparisons  ;
            }
        }
    }
    return comparisons;
}

int n_compar_opt (const std::vector<int>& A, const std::vector<int>& B) {
    int n = A.size();
    std::vector<int> C (n);
    for (int i = 0; i < A.size(); i  ) C[i] = A[i] - B[i];
    std::sort (C.begin(), C.end());
    int comparisons = 0;
    int right_index = n-1;
    for (int left_index = 0; left_index < n; left_index  ) {
        while ((C[left_index] > -C[right_index]) && (right_index >= 0)) {
            right_index --;
        }
        comparisons  = (n-1-right_index);
        if (right_index <= left_index) comparisons --;  // to exclude the case i==j
    }
    comparisons /= 2;   // because pairs (i, j) have been counted twice
    return comparisons;
}

int main() {
    std::vector<int> A = {2, -4, -5, 8, 1, 13, 0, 2};
    std::vector<int> B = {5, 2, -2, -13, 0, 4, 7, 5};
    std::cout << "brute force: " << n_compar_bf (A, B) << "\n";
    std::cout << "new: " << n_compar_opt (A, B) << "\n";
    return 0;
}

CodePudding user response:

I have done the following implementation now, but it seems to give 1 less than the ans in some cases, I can't figure out why. One such input case is included in this code.

#include <iostream>
    #include <algorithm> // for sort
    
    int count_comparisons(std::vector<int>& A, std::vector<int>& B) {
        int comparisons = 0;
    
        // define C as A[i] - B[i] for all i
        std::vector<int> C(A.size());
        for (int i = 0; i < A.size(); i  ) {
            C[i] = A[i] - B[i];
        }
    
        // sort C in ascending order
        std::sort(C.begin(), C.end());
    
        for (int i = 0; i < A.size(); i  ) {
            // count the number of values C[j] to the right of i where C[i] > A[i] - B[i]
            int count = A.size() - (std::upper_bound(C.begin(), C.end(), -C[i 1]) - C.begin()) - 1;
            comparisons  = count;
        }
    
        return comparisons/2;
    }
    
    
    int main() {
        std::vector<int> A = {5,10,5, 7};
        std::vector<int> B = {2, 4, 6, 8};
    
        int comparisons = count_comparisons(A, B);
        std::cout << "Number of comparisons: " << comparisons << std::endl;
    
        return 0;
    }
  • Related