leetcode
leetcode 451 ~ 500
连续数组

连续数组

难度:

标签:

题目描述

给定一个二进制数组 nums , 找到含有相同数量的 01 的最长连续子数组,并返回该子数组的长度。

 

示例 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而不是其他数字,这种转换对解决问题有什么帮助?
将0视为-1而1保持不变的转换,是为了将原问题转化为寻找和为0的最长子数组问题。这是因为,在原数组中,我们需要找到包含相同数量的0和1的子数组。通过将0视为-1,数组中的0和1相互抵消的和为0,这样就可以利用前缀和来快速判断任意子数组中0和1的数量是否相等。此转换使得问题可以通过计算累积和来简化解决,而不必对每个子数组分别计数。
🦆
在哈希表中记录累加和第一次出现的位置和最后一次出现的位置的原因是什么?
在哈希表中记录累加和第一次和最后一次出现的位置,是为了能够快速找到具有相同累加和的最远距离的两个索引。如果两个不同位置的累加和相同,这意味着这两个位置之间的子数组的和为0(即0和1的数量相等)。通过记录这些位置,我们可以计算出每个具有相同累加和的最长子数组的长度,从而找到所有子数组中长度最大的那一个。
🦆
哈希表`sumIJ`在算法中起到了什么关键作用?
哈希表`sumIJ`在算法中起到了存储和检索累加和及其对应索引的关键角色。它允许算法在O(1)时间内查找任何累加和之前是否出现过,并快速检索该累加和的首次和最后一次出现位置。通过这种方式,算法能够有效地判断不同位置之间是否存在和为0的子数组,并计算出这些子数组的长度,以找到最长的符合条件的子数组。
🦆
算法中提到,如果累加和之前出现过,就可以断定这之间的子数组0和1的数量相等。这个逻辑是怎样得出的?
这个逻辑基于前缀和的性质。前缀和是指从数组的开始到当前元素的所有元素的累加和。如果在两个不同的索引处,前缀和相同,这意味着这两个索引之间的子数组的总和为0。在本问题的上下文中,因为0被视为-1,1视为1,这样子数组的和为0意味着其中0的数量等于1的数量。因此,通过检查累加和的重复出现,我们可以找到0和1数量相等的最长子数组。

相关问题

和等于 k 的最长子数组长度

和等于 k 的最长子数组长度