LeetCode. 1248
/*
* (双指针)
* 双指针扫描 r 在前,l 在后。
* 如果当前位置是奇数,则更新计数器,如果当前 [l, r] 有了恰好 k 个奇数,则移动 l 直到不满足,期间统计出长度为 tot。
* 让 ans 累加 tot。
* 如果当前位置是偶数,则说明答案和上一次是奇数的时候一样,直接让 ans 累加上一次的 tot。
* 因为偶数没有影响
*
* 时间复杂度
* 每个位置最多遍历两次,故时间复杂度为 O(n)。
*
* 空间复杂度
* 仅需要常数的额外空间。
*/
class Solution {
public int numberOfSubarrays(int[] nums, int k) {
int n = nums.length;
int cnt = 0, tot = 0, ans = 0;
for (int r = 0, l = 0; r < n; r++) {
if (isOdd(nums[r])) {
cnt++; // 记录[r,l]内奇数的个数
if (cnt == k)
tot = 0; // [r,l]内正好有k个奇数初始化数据,重新计算tot,最终累加到ans
while (cnt == k) {
tot++; // l右移奇数则退出循环,偶数不影响,继续增加子数组
if (isOdd(nums[l])) // 在l向右移动的过程中,如果遇到奇数,则cnt--
cnt--; // 因为进入此if,左端点是奇数,l右移碰到奇数
l++; // 不成立了,所以要退出,在这之前把左端点奇数减掉
} // 为下次做准备
ans += tot;
} else {
ans += tot;
}
}
return ans;
}
private boolean isOdd(int n) {
return n % 2 == 1; // 判断是否为奇数
}
}