LeetCode 982 - Triples with Bitwise AND Equal To Zero


https://leetcode.com/problems/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

X.
https://github.com/cherryljr/LeetCode/blob/master/Triples%20with%20Bitwise%20AND%20Equal%20To%20Zero.java
 * 本题所给出的数据规模对于解题是相当重要的。
 * 首先,因为数组大小在 1000 级别,所以算法的时间复杂度应该在 O(n^2).
 * 因此如果采用暴力求解所有组合(O(n^3))的方法是会超时的。
 * 其次,我们发现 A[i] 的大小不会超过 2^16 = 65536,
 * 这里给了我们一个非常重要的提示:应该利用 A[i] 的大小对状态进行压缩。
 * 因此我们可以很容易想出如下解法:
 *  1. 遍历所有的 两两相与 的数,然后记录在 Map 中
 *  key:两数相与的值; value:该数出现的次数
 *  2. 遍历 A[] 中所有的数 与 Map 中所有的 key 相与,
 *  如果结果为 0,则 res += map.get(a&b)
 * 
 * 时间复杂度:O(n^2 + n*max(A[i]))
 * 空间复杂度:O(n)
 */
    public int countTriplets(int[] A) {
        int res = 0;
        Map<Integer, Integer> map = new HashMap<>();
        for (int a : A) {
            for (int b : A) {
                map.put(a & b, map.getOrDefault(a & b, 0) + 1);
            }
        }

        for (int a : A) {
            for (Map.Entry<Integer, Integer> set : map.entrySet()) {
                if ((a & set.getKey()) == 0) {
                    res += set.getValue();
                }
            }
        }
        return res;
    }


 * Approach 2: Using Array instead of HashMap
 * 因为题目明确给出了数据范围,所以这里可以使用 数组 来替代 HashMap,从而实现对代码的加速。
 * 同时,这里在第二次遍历的时候,当 (a & num) != 0 时,利用了 num += (a & num) - 1 实现加速。
 * 原理在于,因为 (a & num) != 0,所以 [num, num+(a&num)-1] 之间的数都不可能和 a 与出 0 这个结果。
 * 因此可以直接跳过这段区间。
 *
 * 时间复杂度:O(n^2 + n*max(A[i]))
 * 空间复杂度:O(1 << 16) = O(1)
 */
    public int countTriplets(int[] A) {
        // max 表示所能与出来的最大值
        int res = 0, max = -1;
        // 根据数据范围初始化 map[]
        int[] map = new int[1 << 16];
        for (int a : A) {
            for (int b : A) {
                map[a & b]++;
                max = Math.max(max, a & b);
            }
        }

        for (int a : A) {
            for (int num = 0; num <= max; num++) {
                if ((a & num) == 0) {
                    res += map[num];
                } else {
                    num += (a & num) - 1;
                }
            }
        }
        return res;
    }

https://github.com/lrscy/LeetCode/blob/master/Algorithm/982-Triples%20with%20Bitwise%20AND%20Equal%20To%20Zero.cpp
    int countTriplets(vector<int>& A) {
        int n = A.size();
        int inv[1 << 16] = { 0 };
        for( auto a : A ) {
            for( int i = 0; i < ( 1 << 16 ); ++i )
                if( ( a & i ) == 0 )
                    ++inv[i];
        }
        int ret = 0;
        for( int i = 0; i < n; ++i ) {
            for( int j = 0; j < n; ++j ) {
                ret += inv[A[i] & A[j]];
            }
        }
        return ret;
    }

https://leetcode.com/problems/triples-with-bitwise-and-equal-to-zero/discuss/227309/C%2B%2B-naive-O(n-*-n)

First, we process all tuples A[i] and A[j], and store the result of A[i] & A[j] in the hash map tuples. We also count there how many times each result was produced.
Then, we go through the array again, and check each element against all tuples. If it produces zero, we add the tuple counter to the result.
int countTriplets(vector<int>& A, int cnt = 0) {
  unordered_map<int, int> tuples;
  for (auto a : A)
    for (auto b : A) ++tuples[a & b];
  for (auto a : A)
    for (auto t : tuples)
      if ((t.first & a) == 0) cnt += t.second;
  return cnt;
}
Complexity Analysis
Time: O(n * n). We can have 2^16 tuples at most. When n is large, n * n will dominate n * 2^16. So it is O(n * n) in the big O notation.
Memory: O(n) for the first solution; O(2 ^ 16), or, stricter, O(1) for the second one.

https://leetcode.com/problems/triples-with-bitwise-and-equal-to-zero/discuss/226778/C%2B%2B-20-lines56msenumerate-with-memory-(with-Chinese-translation)
  1. 首先枚举 i 和 j,同时使用一个数组 f 记录 A[i] & A[j] 的值所对应的答案个数,即有多少个数字能使得 A[i] & A[j] & x == 0。First, we enumerate i and j, and use a vector f to save the number of solutions corresponding to A[i] & A[j], i.e. the number of x such that A[i] & A[j] & x == 0.
  2. 枚举时,如果对应的 A[i] & A[j] 还没有记录,则暴力枚举 k,求出后将其添加到 f 中。如果有记录,则不再枚举,直接使用这个记录的值。 When enumerating, if there is no record for A[i] & A[j], we will use brute force to compute the number of k, and then save it into the vector f. Otherwise, we can use this record directly.
class Solution {
public:
    int countTriplets(vector<int>& A) {
        int n = A.size(), ans = 0;
        vector<int> f(1 << 16, -1);

        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++) {
                int x = A[i] & A[j];
                if (f[x] == -1) {
                    f[x] = 0;
                    for (int k = 0; k < n; k++)
                        if ((x & A[k]) == 0)
                            f[x]++;
                }
                ans += f[x];
            }

        return ans;
    }
https://zxi.mytechroad.com/blog/bit/leetcode-982-triples-with-bitwise-and-equal-to-zero/
Time complexity: O(n^2 + n * max(A))
Space complexity: O(max(A)
  int countTriplets(vector<int>& A) {
    const int n = *max_element(begin(A), end(A));
    vector<int> count(n + 1);
    for (int a: A)
      for (int b: A)
        ++count[a & b];
    int ans = 0;
    for (int a : A)
      for (int i = 0; i <= n; ++i)
        if ((a & i) == 0) ans += count[i];
    return ans;
  }
X. https://www.acwing.com/solution/leetcode/content/876/
类似于算法 1,我们设计状态 f(i,j)f(i,j) 表示取了 ii 个数字,其按位与的值为 jj 的方案数。
初始时,对于每个 jj,都有 f(0, A[j]) += 1。
转移时,枚举取的第 ii 个数字 A[j]A[j],再枚举上一次按位与的值,转移 f(i, s & A[j]) += f(i - 1, s)。
最后答案为 f(2,0)f(2,0)。
时间复杂度
状态数为 O(m)O(m),每次转移需要 O(n)O(n) 的时间,故总时间复杂度为 O(nm)O(nm)。
实际运行起来比较慢,因为所有 65536 个状态都需要遍历。
状态数位 O(m)O(m),故空间复杂度为 O(m)O(m)。
    int countTriplets(vector<int>& A) {
        int n = A.size();
        vector<vector<int>> f(3, vector<int>(1 << 16, 0));
        for (int i = 0; i < n; i++)
            f[0][A[i]]++;
        for (int i = 1; i < 3; i++)
            for (int s = 0; s < (1 << 16); s++)
                for (int j = 0; j < n; j++)
                    f[i][s & A[j]] += f[i - 1][s];

        return f[2][0];
    }


Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts