题目描述
给你一个整数数组 n u m s nums nums 和一个整数 k k k ,请你返回 n u m s nums nums 中有多少个子数组满足:子数组中所有元素按位 A N D AND AND 的结果为 k k k 。
子数组是数组中连续的非空元素序列。
数据范围
- 1 ≤ n u m s . l e n g t h ≤ 1 0 5 1 ≤ nums.length ≤ 10^5 1≤nums.length≤105
- 0 ≤ n u m s [ i ] , k ≤ 1 0 9 0 ≤ nums[i], k ≤ 10^9 0≤nums[i],k≤109
解题思路
定义如下数组
map<int,int> dp[]
d p [ i ] [ j ] dp[i][j] dp[i][j] 为以 n u m s [ i ] nums[i] nums[i] 结尾的子数组中,按位与的结果为 j j j 的子数组的数量,由 d p [ i ] dp[i] dp[i] 可计算得到 d p [ i + 1 ] dp[i+1] dp[i+1]。
考虑 j j j 的种类,以下列出了每个以 n u m s [ i ] nums[i] nums[i] 结尾的子数组按位与的结果, j j j 种类最多的情况是,每个 x x x 的值可由上一个 x x x 将某一位 1 1 1 置为 0 0 0(与操作不能将某位 0 0 0 置为 1 1 1)得到。
- x = n u m s [ i ] x = nums[i] x=nums[i]
- x = n u m [ i − 1 ] & n u m s [ i ] x = num[i-1]\ \&\ nums[i] x=num[i−1] & nums[i]
- x = n u m [ i − 2 ] & n u m [ i − 1 ] & n u m s [ i ] x =num[i-2]\ \&\ num[i-1]\ \&\ nums[i] x=num[i−2] & num[i−1] & nums[i]
- …
由于 n u m s [ i ] nums[i] nums[i] 最多有 32 32 32 位为 1 1 1,所以, j j j 的种类不超过 32 32 32,时间和空间复杂度满足要求。
代码实现
long long countSubarrays(vector<int> &nums, int k) {long long res = 0;unordered_map<int, int> pre;for (auto &num: nums) {unordered_map<int, int> cur = {{num, 1}};// num[i]本身值为kif (num == k)res++;// 由pre得到curfor (auto &[r, m]: pre) {int t = r & num;cur[t] += m;if (t == k)res += m;}pre = cur;}return res;
}
时间复杂度: O ( n m ) O(nm) O(nm),其中, n n n 为 n u m s nums nums 的长度, m m m 为解题思路中 j j j 的种类。
空间复杂度: O ( m ) O(m) O(m)。
END
文章文档:公众号 字节幺零二四
回复关键字可获取本文文档。
题目来源:力扣第134场双周赛T4:子数组按位与值为K的数目
文章声明:题目来源 力扣 平台,如有侵权,请联系删除!