Given an array of integers nums and an integer k, return the number of subarrays of nums where the bitwise AND of the elements of the subarray equals k.
To find the number of subarrays whose bitwise AND equals k, we can leverage the fact that the AND operation is monotonic (AND-ing more numbers can only keep or reduce set bits). For each position, we can track all possible AND values ending at that position and count how many times k appears.
We iterate through the array, and for each element, we keep a map (or set) of all possible AND values for subarrays ending at the current index, along with their counts. For each previous AND value, we compute the AND with the current number and update the map. We also start a new subarray at the current index. We sum the counts where the AND value equals k.
from collections import Counter
from typing import List
defcountSubarrays(nums: List[int], k: int) -> int:
ans =0 prev = Counter()
for num in nums:
curr = Counter()
curr[num] +=1for val, cnt in prev.items():
curr[val & num] += cnt
ans += curr[k]
prev = curr
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<vector>#include<unordered_map>usingnamespace std;
intcountSubarrays(vector<int>& nums, int k) {
int ans =0;
unordered_map<int, int> prev;
for (int num : nums) {
unordered_map<int, int> curr;
curr[num]++;
for (auto& [val, cnt] : prev) {
curr[val & num] += cnt;
}
ans += curr[k];
prev = move(curr);
}
return ans;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.*;
publicclassSolution {
publicintcountSubarrays(int[] nums, int k) {
int ans = 0;
Map<Integer, Integer> prev =new HashMap<>();
for (int num : nums) {
Map<Integer, Integer> curr =new HashMap<>();
curr.put(num, curr.getOrDefault(num, 0) + 1);
for (Map.Entry<Integer, Integer> entry : prev.entrySet()) {
int val = entry.getKey() & num;
curr.put(val, curr.getOrDefault(val, 0) + entry.getValue());
}
ans += curr.getOrDefault(k, 0);
prev = curr;
}
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
funcountSubarrays(nums: IntArray, k: Int): Int {
var ans = 0var prev = mutableMapOf<Int, Int>()
for (num in nums) {
val curr = mutableMapOf<Int, Int>()
curr[num] = curr.getOrDefault(num, 0) + 1for ((val_, cnt) in prev) {
val andVal = val_ and num
curr[andVal] = curr.getOrDefault(andVal, 0) + cnt
}
ans += curr.getOrDefault(k, 0)
prev = curr
}
return ans
}
⏰ Time complexity: O(n * log(maxA)) where n is the length of nums and maxA is the maximum value in nums (since the number of unique AND values per position is at most log(maxA)).
🧺 Space complexity: O(log(maxA)) for the map of AND values per position.