[LeetCode 982] Triples with Bitwise AND Equal To Zero

Given an array of integers A, find the number of triples of indices (i, j, k) such that:

  • 0 <= i < A.length
  • 0 <= j < A.length
  • 0 <= k < A.length
  • A[i] & A[j] & A[k] == 0, where & represents the bitwise-AND operator.

 

Example 1:

Input: [2,1,3]
Output: 12
Explanation: We could choose the following i, j, k triples:
(i=0, j=0, k=1) : 2 & 2 & 1
(i=0, j=1, k=0) : 2 & 1 & 2
(i=0, j=1, k=1) : 2 & 1 & 1
(i=0, j=1, k=2) : 2 & 1 & 3
(i=0, j=2, k=1) : 2 & 3 & 1
(i=1, j=0, k=0) : 1 & 2 & 2
(i=1, j=0, k=1) : 1 & 2 & 1
(i=1, j=0, k=2) : 1 & 2 & 3
(i=1, j=1, k=0) : 1 & 1 & 2
(i=1, j=2, k=0) : 1 & 3 & 2
(i=2, j=0, k=1) : 3 & 2 & 1
(i=2, j=1, k=0) : 3 & 1 & 2

 

Note:

  1. 1 <= A.length <= 1000
  2. 0 <= A[i] < 2^16

 

Solution that you came up: there are 3 cases: 1. all 3 indices are the same; 2. 2 indices are the same; 3. all 3 indices are different.

case 1: count how many 0s;

case 2: has pattern(x, x, y), fix x then find y such that A[x] & A[y] is 0, there are 3 positions that we can put y into.

case 3: dp[i] is the number of pairs(x != y) so far such that (A[x] & A[y]) == i. Loop through A and fix the 3rd position index of a triple, then check all possible pairs' & value to see if we can get a valid triple. If we can, add 3! (Order matters). After considering all possible triples that end at the current index, update dp[] using the current number as the 2nd index.

 

Runtime is O(N * N + N * 2^16), space is O(2^16).

 

class Solution {
    public int countTriplets(int[] A) {
        int ans = 0;
        //(0,0,0)
        for(int v : A) {
            if(v == 0) {
                ans++;
            }
        }
        //(x,x,y),(x,y,x),(y,x,x)
        for(int i = 0; i < A.length; i++) {
            for(int j = 0; j < A.length; j++) {
                if(j == i) {
                    continue;
                }
                if((A[i] & A[j]) == 0) {
                    ans += 3;
                }
            }
        }
        //(x,y,z) and all its permutations
        //dp[i]: the number of pairs(x != y) so far such that (A[x] & A[y]) == i
        if(A.length >= 3) {
            int n = 1 << 16;
            int[] dp = new int[n];
            dp[A[0] & A[1]]++;
            for(int k = 2; k < A.length; k++) {
                for(int v = 0; v < n; v++) {
                    if((v & A[k]) == 0) {
                        ans += dp[v] * 6;
                    }
                }
                for(int i = 0; i < k; i++) {
                    dp[A[i] & A[k]]++;
                }
            }            
        }
        return ans;
    }
}

 

 

 

A more concise solution

Instead of computing 3 separate cases, we can just define dp[i] as the number of index pairs (x, y) such that (A[x] & A[y]) == i. Then loop through all possible pairs including same index to update dp. Then we loop through A to fill in a 3rd index to make triples. Since each index is unique, we'll not have double counting. For each index, loop through all pairs' & value to check if we can make a valid triple, update final count. Both the runtime and space complexity are the same with the above solution.

 

 

class Solution {
public int countTriplets(int[] A) {
        int ans = 0;
        int[] dp = new int[1 << 16];
        for(int i = 0; i < A.length; i++){
            for(int j = 0; j < A.length; j++){
                int v = A[i] & A[j];
                dp[v]++;
            }
        }
        for(int i = 0; i < A.length; i++){
            for(int j = 0; j < dp.length; j++) {
                if((A[i] & j) == 0){
                    //use i as the 3rd index
                    ans += dp[j];
                }
            }
        }
        return ans;
    }
}

 

posted @ 2020-09-26 02:17  Review->Improve  阅读(193)  评论(0编辑  收藏  举报