Given an integer array nums, return the number of AND triples.
An AND triple is a triple of indices (i, j, k)
such that:
0 <= i < nums.length
0 <= j < nums.length
0 <= k < nums.length
nums[i] & nums[j] & nums[k] == 0
, where &
represents the bitwise-AND operator.
Example 1:
Input: nums = [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
Example 2:
Input: nums = [0,0,0] Output: 27
Constraints:
1 <= nums.length <= 1000
0 <= nums[i] < 216
This problem asks us to find the number of triplets (i, j, k) in an array nums
such that the bitwise AND of nums[i]
, nums[j]
, and nums[k]
is 0. A brute-force approach would have a time complexity of O(n³), which is inefficient for larger arrays. The provided solution optimizes this using a clever counting strategy.
Approach:
The solution leverages the commutative and associative properties of the bitwise AND operation. It breaks down the problem into two steps:
Count Pairwise ANDs: It first iterates through all possible pairs (i, j) in nums
and calculates the bitwise AND of nums[i]
and nums[j]
. It uses a Counter
(Python) or a frequency array (other languages) to store the frequency of each unique AND result. This step effectively pre-computes the results of pairwise AND operations.
Check for Zero AND: For each unique pairwise AND result (xy
), it iterates through the array again. If the bitwise AND of xy
and nums[k]
is 0 for any k
, it means we've found a triplet (i, j, k) where the overall AND is 0. The count of such triplets is added to the final answer, multiplying the frequency of the pair's AND result (cnt[xy]
) by the number of times a suitable z
was found.
Time and Space Complexity Analysis:
Time Complexity: O(n² + nM), where n is the length of nums
and M is the maximum value in nums
. The first step (pairwise ANDs) takes O(n²) time. The second step iterates through nums
for each unique pairwise AND result. In the worst case, the number of unique pairwise AND results is O(M), so the second step can take up to O(nM) time.
Space Complexity: O(M). The space complexity is dominated by the cnt
array (or Counter
in Python) which stores the frequencies of pairwise AND results. The size of this array is proportional to the maximum value in nums
(M).
Code Explanation (Python):
from collections import Counter
class Solution:
def countTriplets(self, nums: List[int]) -> int:
cnt = Counter(x & y for x in nums for y in nums) # Count pairwise ANDs
return sum(v for xy, v in cnt.items() for z in nums if xy & z == 0) # Check for zero AND
The Python code is concise due to the use of list comprehensions and the Counter
object. It elegantly handles the counting and summation steps. Other language versions achieve the same functionality using arrays and loops. The core logic remains consistent across all implementations.
Example Walkthrough (Python):
Let's consider nums = [2, 1, 3]
.
Pairwise ANDs:
Check for Zero AND:
xy = 0
, the count is 2. 0 & z == 0
for all z
in nums
, so we add 2 * 3 = 6 to the answer.xy = 1
, the count is 2. 1 & 1 == 1
, 1 & 2 == 0
, 1 & 3 == 1
, so we add 2 * 1 = 2 to the answer.xy = 2
, the count is 2. 2 & 1 == 0
, 2 & 2 == 0
, 2 & 3 == 2
, so we add 2 * 1 = 2 to the answer.xy = 3
, the count is 1. No z satisfies 3 & z == 0
, so we add 0 to the answer.The total answer becomes 6 + 2 + 2 = 12.
This detailed explanation provides a comprehensive understanding of the solution's approach, code implementation, and complexity analysis. The example walkthrough clarifies the process step-by-step.