1 比 0 多的子数组个数
难度:
标签:
题目描述
代码结果
运行时间: 107 ms, 内存: 21.3 MB
/*
题目思路:
1. 使用流处理数组。
2. 将数组转换为1和-1(0变为-1)。
3. 使用前缀和记录当前的1和-1数量差。
4. 使用一个哈希表来记录当前差值出现的次数。
5. 最后累加满足条件的子数组个数。
*/
import java.util.HashMap;
import java.util.stream.IntStream;
public class SubarrayCountStream {
public int subarraysWithMoreOnesThanZeros(int[] nums) {
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
int[] diff = {0};
return IntStream.of(nums).map(num -> num == 1 ? 1 : -1).reduce(0, (count, num) -> {
diff[0] += num;
count += map.getOrDefault(diff[0], 0);
map.put(diff[0], map.getOrDefault(diff[0], 0) + 1);
return count;
});
}
public static void main(String[] args) {
SubarrayCountStream scs = new SubarrayCountStream();
int[] nums = {1, 0, 1, 0, 1};
System.out.println(scs.subarraysWithMoreOnesThanZeros(nums)); // Output: 9
}
}
解释
方法:
该题解使用前缀和的思路来解决问题。通过维护一个前缀和数组 cnts,其中 cnts[i] 表示前缀和为 i 的子数组个数。遍历数组 nums,对于每个元素,如果是 1,则将前缀和加 1;如果是 0,则将前缀和减 1。对于当前前缀和 s,cnt 变量累加 cnts[s],表示以当前元素结尾、满足条件的子数组个数。最后将 cnt 累加到答案 ans 中,并对 10^9 + 7 取模。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
题解中提到的前缀和数组cnts用来记录前缀和的子数组个数,但如何处理可能出现的负数前缀和?
▷🦆
在题解逻辑中,当遍历到数字0时,为什么需要从cnt变量中减去cnts[s]?这样的操作是基于什么考虑?
▷🦆
题解中使用了取模操作(10^9 + 7),这种操作在算法中通常有什么作用?为什么需要在这个问题中使用它?
▷🦆
题解中的前缀和s是如何在遍历过程中更新的,这种更新方式与子数组的计数有什么直接关系?
▷