leetcode1493. 删掉一个元素以后全为 1 的最长子数组

给你一个二进制数组 nums ,你需要从中删掉一个元素。

请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。

如果不存在这样的子数组,请返回 0 。

示例 1



输入:nums = [1,1,0,1]
输出:3
解释:删掉位置 2 的数后,[1,1,1] 包含 3 个 1 。



示例 2



输入:nums = [0,1,1,1,0,1,1,0,1]
输出:5
解释:删掉位置 4 的数字后,[0,1,1,1,1,1,0,1] 的最长全 1 子数组为 [1,1,1,1,1] 。



示例 3



输入:nums = [1,1,1]
输出:2
解释:你必须要删除一个元素。



示例 4



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



示例 5



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



提示:

  • 1 <= nums.length <= 10^5
  • nums[i] 要么是 0 要么是 1

方法:记录0的索引位置

思路:

我们希望得到的是两个最长的全为1的子数组,中间只有1个0,这样删除之后,这两个全为1的数组的长度加在一起就为答案。由于数组是二进制的,只有1和0,那么我们需要找到0的位置,然后把每个0左右的全为1数组长度相加,找出最大值即可。

我们维护一个字典,键为0的索引,值为这个0前面的全为1的数组长度,如果连续两个0出现,那么第二个0位置对应的值为0,表示这个0前面没有1。同时维护一个数组zero,存放所有0的位置。

我们遍历这个整个nums数组,填写字典和zero数组。

然后我们遍历zero数组,zero[i]和zero[i+1]在字典中的值之和,即为zero[i]位置的0删除后,全为1的子数组长度。我们找到最大的即可。同时需要注意的是,对于最后一个zero,zero[i+1]不存在,因此需要在上面遍历nums结束后,在zero中加上位置n+1,表示末尾,这样最后一个0可以将它前面的以及后面的全为1的子数组加在一起。

还需要考虑的是,如果zero数组只有一个元素,那么说明就是末尾n+1,则整个数组不存在0,只有1,根据题意,必须删除一个元素,直接返回n-1

  • 遍历了1次nums,一次zero,时间复杂度O(2N),渐进时间复杂度为O(N)。
  • 使用了一个字典和一个数组,空间复杂度为O(N)

代码:



class Solution:
    def longestSubarray(self, nums: List[int]) -> int:
        zero = []
        #键为这个都为1的子数组结束后的0的位置,值为这个子数组的长度
        leng_idx = dict()
        n = len(nums)
        #temp为当前遍历到的全为1的子数组的长度
        temp = 0
        ans = 0
        for i in range(n):
            if nums[i]:
                temp += 1
            else:
                leng_idx[i] = temp
                temp = 0
                #保存0的位置
                zero.append(i)
        #保存最后一个子数组以及把末尾n+1当作0
        leng_idx[i+1] = temp
        zero.append(i+1)
        #如果只有一个元素,说明没有0,返回n-1
        if len(zero) == 1:
            return n-1
        else:
            #遍历所有的0前后的数组长度之和,找到最长的
            for i in range(len(zero)-1):
                ans = max(ans,leng_idx[zero[i]]+leng_idx[zero[i+1]])
            return ans



结果:




java 获取数组最后一条数据_获取数组最后一个元素