LeetCode连续数组 前缀和

525. 连续数组

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

示例 1:

输入: nums = [0,1]

输出: 2

说明: [0, 1] 是具有相同数量 0 1 的最长连续子数组。

示例 2:

输入: nums = [0,1,0]

输出: 2

说明: [0, 1] ( [1, 0]) 是具有相同数量01的最长连续子数组。

思路:

    看到这一题,因为是连续子数组所以想尝试用滑动窗口来做,但仔细看题意给的条件好像又没法进行窗口收缩的判断,所以不能用滑动窗口。

    这道题得用一个很巧妙的办法:将0变成-1,这样每对0和1的和其实就是-1+1=0,然后我们使用老生常谈的前缀和的方法:

1.当前缀和出现0时,就说明从这之前01的个数是相同的;

2.当相同的前缀和出现两次时,也说明这两次位置之间的范围中0和1个数是相同的。

  代码具体实现时,我们用一个哈希表来存储非0前缀和以及它第一次出现的位置。具体细节直接看吧,写了很清楚的注释~~

代码:

class Solution(object):
    def findMaxLength(self, nums):
    #将原数组的0全部变为-1 则问题等价于“元素值总和为0的连续数组” 
        lenth = len(nums)
        for i in range(lenth):
            if nums[i]==0:nums[i]=-1#把0全都变成-1
        qian = [0]*lenth#前缀和数组
        qian[0]=nums[0]#初始化第一个
        maxx=0
        for i in range(1,lenth):#计算前缀和数组
            qian[i]=qian[i-1]+nums[i]#逐个累加即可
        hashmap={}#存储非0前缀和的哈希表
        for i in range(lenth):
            #对前缀和的判断有两种 一种是前缀和为0,这最直接,则说明这往前和为0
            if qian[i]==0:maxx = max(maxx,i+1)
            #第二种就是出现两次或以上的前缀和,他们之间的和为0
            if qian[i] not in hashmap:#如果第一次出现,则放入哈希表
                hashmap[qian[i]]=i#key是前缀和的值,value是它的位置
            else:#如果不是第一次出现,则取第一次出现的位置做距离计算,并尝试更新最大值
                maxx = max(maxx,i-hashmap[qian[i]])
        return maxx

  如果提交运行后会发现,这其实是一个效率不太高的写法,因为前缀和可以直接压缩到常数级别而并不一定要用数组。不过这样写思路最清晰也最方便理解,我还是喜欢这种方式~

猜你喜欢

转载自blog.csdn.net/weixin_44492824/article/details/123950583