简体   繁体   中英

How to find triplets { x , y , z } from three sorted A, B, C such that x < y < z in O(n)?

Suppose I have three sorted arrays

A: { 4, 9 }

B: { 2, 11}

C: { 12, 14}

Then the no of triplets { x, y, z } such that x belongs to A, y belongs to B and z belongs to C such that x < y < z is -> 4

I know O( n ^3 ) algo but how to do it in O(n). Where n is the length of the array.

Initialize a 'count' variable to zero.

Find the lengths of the three lists in linear time, if not given.

Merge the three lists into one sorted list in linear time, keeping track of which of the original lists each belonged to.

Parse the merged list. As you do so, keep track of the number of elements from A you have seen, and from C that you have NOT seen. Each time you encounter a member from list B, increase your count by (A seen) * (C not seen), both as of the current index. What we're doing here is, for ever element from B, counting the number of ways we can find a smaller element from A and a bigger element from C.

You can also keep track of B's and stop after the last one in the merged list.

O(n)

Eg, A: { 4, 9 }

B: { 2, 11}

C: { 12, 14}

(2,B), (4,A), (9,A), (11,B), (12,C), (14,C)

initialize: count = 0, A_seen = 0, C_unseen=2
index 0: A_seen = 0, C_unseen = 2, count = 0 + 0*2 = 0
index 1: A_seen = 1, C unseen = 2, count unchanged
index 2: A_seen = 2, C unseen = 2, count unchanged
index 3: A_seen = 2, C unseen = 2, count = 0 + 2*2 = 4
We can stop here since we're out of B's.

-- edit --

Easy optimization: don't merge the lists, but just iterate through B, keeping track of the index of the largest smaller element of A and smallest larger element of C, then proceed as before. This is still linear and has less overhead.

You can do it using memorize count with binary search.. complexity: O(n * logn) .

For each element of B search greater value position from array C. Then you can count no of valid y < z. it will be (n - position of greater value)

Now for each element of A search greater value position from array B. Then you can count no of valid x < y. it will be (n - position of greater value)..Here you need to take sum of count of each valid position of B.

sample code here:

#include <bits/stdc++.h>
using namespace std;

int bs(int l, int h, int v, int A[]) {
    int m;
    while (l <= h) {
        m = (l + h) / 2;
        if (A[m] < v) {
            l = m + 1;
        } else {
            h = m - 1;
        }
    }
    return l;
}

int main() {
    int A[] = {4,9};
    int B[] = {2,11};
    int C[] = {12,14};
    int dp[] = {0};
    int n = 2, i, ans = 0, p;
    for (i = 0; i < n; i++) {
        p = bs(0, n-1, B[i], C);
        dp[i] = i ? dp[i-1] + n-p : n-p;
    }
    for (i = 0; i < n; i++) {
        p = bs(0,n-1, A[i], B);
        if (p) {
            ans += (dp[n-1]-dp[p-1]);
        } else {
            ans += dp[n-1];
        }
    }
    printf("%d\n", ans);
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM