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

题目描述

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

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

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

输入样例

在这里插入图片描述

提示

在这里插入图片描述

解题思路

根据题目意思,我们可以把问题的解决分为两个步骤:
1.找出所有连续1的段
2.看看他们能不能结合
什么意思呢?看下图
在这里插入图片描述
假设输入为[0, 1, 1, 1, 0, 1, 1, 0, 1]
显然,连续1的段有上图3段;接下来,我们记录这3段中最大的一段的长度,即3(最长子数组);然后,我们需要看看这三个段能否结合变成更大的段,注意:根据题目要求,只能是邻接的段才能进行组合,即第一段和第二段能组合,第二段第三段可以组合(他们之间只有一个0)。不难看出,第一段和第二段结合后长度为5,那么更新最长子数组长度为5,第二和第三段结合为3<5。那么最终答案就是5.

代码(py3)

class Solution(object):

    def longestSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """

        getMax = lambda x, y: x if x > y else y
        # 只有0
        if nums.__contains__(1) is False:
            return 0
        # 只有1
        if nums.__contains__(0) is False:
            return len(nums) - 1
        else:
            idx_len = {}
            longest_length = 0
            start = 0
            length = 0
            is_new = True
            for idx, i in enumerate(nums):
                if i == 1:
                    if is_new:
                        start = idx
                        is_new = False
                    # 如果是最后一个
                    if idx + 1 == len(nums):
                        idx_len[start] = idx + 1 - start
                # 遇到0
                if i == 0 and is_new is False:
                    length = idx - start
                    idx_len[start] = length
                    is_new = True
                    if length >= longest_length:
                        longest_length = length
        # 找是否有可以拼接的段
        keys = list(enumerate(idx_len.keys()))
        for idx, _ in keys:
            if idx + 1 == len(idx_len):
                return getMax(idx_len[keys[idx][1]], longest_length)
            this_idx = idx
            next_idx = idx + 1
            if keys[next_idx][1] - (keys[this_idx][1] + idx_len[keys[this_idx][1]]) == 1:
                # 可以拼接, 如果更大就更新
                longest_length = getMax(idx_len[keys[this_idx][1]] + idx_len[keys[next_idx][1]], longest_length)
        return longest_length

细节解释

遇到1

对于如何找出所有连续1的段,做法是遍历list,同时设置一个bool的is_new变量,其初始值为True,每次遇到1时,无非是两种情况:
1.这个1是独立的一个段,比如上面例子中的第三段
2.这不是独立的一个段
那么针对这两种情况,可以用is_new进行判断,如果遇到1,且is_new==True,说明这是一段新的,那么我们就记录,同时置is_new为False

遇到0

同样的遇到0时,会有一下两个情况:
1.这个0结束了一个段,即0使得连续的1中断
2.0单纯出现了,没有段被中断
什么意思呢,比如[0, 0, 1, 1, 0, 1, 0]
这个输入中,前面两个0和最后一个0就属于第二种情况,第三个0,属于第一种情况。
针对第一种情况,做法就是当遇到0时,判断is_new是否为False,is_new为False,那么就说明,这个0中断了连续1的段,我们需要把被中断的段记录;对于第二种情况,直接不用处理。

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值