Skip to content

Latest commit

 

History

History
226 lines (147 loc) · 5.91 KB

0525._Contiguous_Array.md

File metadata and controls

226 lines (147 loc) · 5.91 KB

525. Contiguous Array

难度: Medium

刷题内容

原题连接

内容描述

Given a binary array, find the maximum length of a contiguous subarray with equal number of 0 and 1.

Example 1:
Input: [0,1]
Output: 2
Explanation: [0, 1] is the longest contiguous subarray with equal number of 0 and 1.
Example 2:
Input: [0,1,0]
Output: 2
Explanation: [0, 1] (or [1, 0]) is a longest contiguous subarray with equal number of 0 and 1.
Note: The length of the given binary array will not exceed 50,000.

解题方案

思路 1 - 时间复杂度: O(N^2)- 空间复杂度: O(N)******

前缀和与后缀和,超时

class Solution:
    def findMaxLength(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        prefix = [0] * (len(nums) + 1)
        suffix = [0] * (len(nums) + 1)
        sums = sum(nums)
        for i in range(1, len(nums)+1):
            prefix[i] = prefix[i-1] + nums[i-1]
        for i in range(1, len(nums)+1):
            suffix[i] = suffix[i-1] + nums[len(nums)-i]
        res = 0
        for i in range(len(nums)+1):
            for j in range(len(nums) - i + 1):
                tmp = sums - suffix[j] - prefix[i]
                if (len(nums) - i - j) % 2 == 0 and tmp == (len(nums) - i - j) // 2:
                    res = max(res, (len(nums) - i - j))
        return res

思路 2 - 时间复杂度: O(N^2)- 空间复杂度: O(N)******

segment tree, 超时

import math
class SegmentTree(object):
    def __init__(self, nums):
        self.nums = nums
        self.range_len = len(nums)
        power = math.ceil(math.log(self.range_len, 2)) if self.range_len else 0
        self.st = [0] * (2 ** (power + 1))
        self.constrcut(nums, 0, self.range_len - 1, 0)

    # A utility function to get the middle index from corner indexes.
    def getMid(self, start, end):
        return start + (end - start) // 2

    # A recursive function that constructs Segment Tree for array[start..end].
    # cur is the index of current node in segment tree self.st
    # Time Complexity for tree construction is O(n).
    # There are total 2n-1 nodes, and value of every node is calculated only once in tree construction.
    def constrcut(self, nums, start, end, cur):  # O(N)
        if start > end:
            return
        if start == end:
            self.st[cur] = nums[start]
            return nums[start]
        mid = self.getMid(start, end)
        self.st[cur] = self.constrcut(nums, start, mid, 2 * cur + 1) + \
                       self.constrcut(nums, mid + 1, end, 2 * cur + 2)
        return self.st[cur]

    def getSumHelper(self, start, end, query_start, query_end, cur):
        if query_start <= start and query_end >= end:
            return self.st[cur]
        if end < query_start or start > query_end:
            return 0
        mid = self.getMid(start, end)
        return self.getSumHelper(start, mid, query_start, query_end, 2 * cur + 1) + \
               self.getSumHelper(mid + 1, end, query_start, query_end, 2 * cur + 2)

    # Time complexity to query is O(Logn).
    # To query a sum, we process at most four nodes at every level and number of levels is O(Logn).
    def getSum(self, query_start, query_end):
        if query_start < 0 or query_end > self.range_len - 1 or query_start > query_end:
            # print('Invalid Input')
            return -1
        return self.getSumHelper(0, self.range_len - 1, query_start, query_end, 0)

    # idx --> index of the element to be updated. This index is in input nums.
    def updateValueHelper(self, start, end, idx, diff, cur):
        if idx < start or idx > end:
            return
        self.st[cur] += diff
        if end != start:
            mid = self.getMid(start, end)
            self.updateValueHelper(start, mid, idx, diff, 2 * cur + 1)
            self.updateValueHelper(mid + 1, end, idx, diff, 2 * cur + 2)

    # The time complexity of update is also O(Logn).
    # To update a leaf value, we process one node at every level and number of levels is O(Logn).
    def updateValue(self, idx, new_val):  # O(lgN)
        if idx < 0 or idx > self.range_len - 1:
            # print('Invalid Input')
            return
        diff = new_val - self.nums[idx]
        self.nums[idx] = new_val
        self.updateValueHelper(0, self.range_len - 1, idx, diff, 0)
        
class Solution:
    def findMaxLength(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        s = SegmentTree(nums)
        res = 0
        for i in range(len(nums)):
            for j in range(len(nums)):
                tmp = s.getSum(i, j)
                if (j - i + 1) % 2 == 0 and tmp == (j - i + 1) // 2:
                    res = max(res, (j - i + 1))
        return res

思路 3 - 时间复杂度: O(N)- 空间复杂度: O(N)******

一次遍历,我们用个cnt来记录当前一共碰到了几个1,即碰到1的话cnt就加1,碰到0的话cnt就减1

然后再搞一个字典记录第一次出现某一个cnt值所对应的index值,比如我们第一次碰到了cnt = 2的时候是在index为7的时候,然后在index为16的时候cnt又等于2了, 那肯定说明在index 8到16的这个区间中1和0的数量相等,就更新一下我们的res

比如最开始的时候,cnt为0,第一次碰到cnt为0的情况我们还没有开始遍历呢,此时index自然为-1

beats 31.12%

class Solution:
    def findMaxLength(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res, cnt, lookup = 0, 0, {0: -1}
        for i, num in enumerate(nums):
            if num == 1:
                cnt += 1
            else:
                cnt -= 1
            if cnt in lookup:
                res = max(res, i - lookup[cnt])
            else:
                lookup[cnt] = i
        return res