连续数组
难度:
标签:
题目描述
给定一个二进制数组 nums
, 找到含有相同数量的 0
和 1
的最长连续子数组,并返回该子数组的长度。
示例 1:
输入: nums = [0,1] 输出: 2 说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。
示例 2:
输入: nums = [0,1,0] 输出: 2 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
提示:
1 <= nums.length <= 105
nums[i]
不是0
就是1
代码结果
运行时间: 105 ms, 内存: 24.4 MB
/*
* 题目思路:
* 与传统的遍历方法相同,我们将0视为-1,计算前缀和。
* 我们使用Stream API和Collectors来简化代码。
* 通过Optional和map来减少代码的分支结构。
*/
import java.util.stream.IntStream;
import java.util.HashMap;
public class Solution {
public int findMaxLength(int[] nums) {
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, -1);
return IntStream.range(0, nums.length)
.map(i -> nums[i] == 1 ? 1 : -1)
.reduce(new int[]{0, 0}, (acc, val) -> {
acc[0] += val;
acc[1] = Math.max(acc[1], map.getOrDefault(acc[0], i - map.get(acc[0])));
map.putIfAbsent(acc[0], i);
return acc;
}, (a, b) -> a)[1];
}
}
解释
方法:
这道题目的解法使用了一种基于前缀和和哈希表的技术。具体思路是,首先将数组中的0视为-1,这样问题转换为找出和为0的最长子数组。遍历数组时,我们维护一个累加和anscnt,每遇到1增加1,每遇到0减少1。使用一个哈希表sumIJ来记录每个累加和第一次出现的位置和最后一次出现的位置。如果在某个位置的累加和之前出现过,说明从上一次出现该累加和的位置到当前位置的子数组中0和1的数量相等。通过比较所有这样的子数组,找到最长的一个。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在这个问题中选择将0视为-1而不是其他数字,这种转换对解决问题有什么帮助?
▷🦆
在哈希表中记录累加和第一次出现的位置和最后一次出现的位置的原因是什么?
▷🦆
哈希表`sumIJ`在算法中起到了什么关键作用?
▷🦆
算法中提到,如果累加和之前出现过,就可以断定这之间的子数组0和1的数量相等。这个逻辑是怎样得出的?
▷