leetcode 单调栈 42接雨水 84柱状图最大矩形

记一下刷的题

42接雨水

1.动态规划,时间复杂度O(n)

class Solution:
    def trap(self, height: List[int]) -> int:
        if not height:return 0
        n = len(height)
        max_left=[0]*n
        max_right=[0]*n
        max_left[0]=height[0]
        max_right[-1]=height[-1]
        #找位置i左边最大值
        for i in range(1,n):
            max_left[i]=max(height[i],max_left[i-1])
        #找出位置i右边的最大值
        for i in range(n-2,-1,-1):
            max_right[i]=max(height[i],max_right[i+1])
        res = 0
        for i in range(n):
            res += min(max_left[i],max_right[i])-height[i]
        return res
    

2.双指针,时间复杂度O(n)

class Solution:
    def trap(self, height: List[int]) -> int:
        if not height:return 0
        left = 0
        right = len(height)-1
        res=0
        #记录左右最大值
        left_max = height[left]
        right_max=height[right]
        while left<right:
            if height[left]<height[right]:
                if left_max>height[left]:
                    res += left_max-height[left]
                else:
                    left_max=height[left]
                left += 1
            else:
                if right_max>height[right]:
                    res += right_max-height[right]
                else:
                    right_max = height[right]
                right -=1
        return res

3.栈,时间复杂度O(n)

class Solution:
    def trap(self, height: List[int]) -> int:
        if not height:return 0
        n = len(height)
        stack = []
        res = 0
        for i in range(n):
            #print(stack)
            while stack and height[stack[-1]] < height[i]:
                tmp = stack.pop()
                if not stack: break
                res += (min(height[i], height[stack[-1]]) - height[tmp]) * (i-stack[-1] - 1)
            stack.append(i)
        return res

84柱状图最大矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。

  1. 单调栈方法
class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        heights.append(0)
        stack=[0]
        area=0
        for i in range(1,len(heights)):
            if heights[i]>=heights[stack[-1]]:
                stack.append(i)
            else:
                while stack and heights[i]<heights[stack[-1]]:
                    x= stack.pop(-1)#弹出栈顶
                    if len(stack) != 0:
                        area = max(area,heights[x]*(i-stack[-1]-1))
                    else:
                        area = max(area,heights[x]*i)
                stack.append(i)
        return area

85 最大矩形

给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例:

输入:
[
[“1”,“0”,“1”,“0”,“0”],
[“1”,“0”,“1”,“1”,“1”],
[“1”,“1”,“1”,“1”,“1”],
[“1”,“0”,“0”,“1”,“0”]
]
输出: 6

  1. 类似84的单调栈方法
class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        if not matrix or not matrix[0]:
            return 0
        res = 0
        n = len(matrix[0])
        heights=[0]*(n+1)
        for row in matrix:
            for i in range(n):
                heights[i]=heights[i]+1 if row[i]=='1' else 0
            stack = []
            for i in range(len(heights)):
                #当前位置小于栈顶位置时候计算
                while stack and heights[stack[-1]]>heights[i]:
                    h = heights[stack.pop()]
                    area = h*(i-stack[-1]-1 if stack else i)
                    res = max(res,area)
                stack.append(i)
        return res
                                        
  1. 看到用二进制
class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        if not matrix or not matrix[0]:
            return 0
        nums = [int(''.join(row),base=2) for row in matrix]
        ans,N = 0,len(nums)
        for i in range(N):
            j,num = i,nums[i]
            while j<N:
                num = num&nums[j]
                if not num:
                    break
                l,curnum = 0,num
                while curnum:
                    l += 1
                    curnum = curnum&(curnum<<1)
                ans = max(ans,l*(j-i+1))
                j += 1
        return ans

316 去除重复字母

给定一个仅包含小写字母的字符串,去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

示例 1:

输入: “bcabc”
输出: “abc”
示例 2:

输入: “cbacdcbc”
输出: “acdb”

class Solution:
    def removeDuplicateLetters(self, s: str) -> str:
        mid_list = ['0']#0比一切字母小,不用判断空
        for index,alpha in enumerate(s):
            if alpha not in mid_list:
                #当前字母比栈顶字母小、字符串之后还会出现栈顶字母,栈顶字母出站
                while alpha <mid_list[-1] and s[index:].count(mid_list[-1])>0:
                    mid_list.pop(-1)
                mid_list.append(alpha)
        return ''.join(mid_list[1:])   

321 拼接最大数

给定长度分别为 m 和 n 的两个数组,其元素由 0-9 构成,表示两个自然数各位上的数字。现在从这两个数组中选出 k (k <= m + n) 个数字拼接成一个新的数,要求从同一个数组中取出的数字保持其在原数组中的相对顺序。

求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。

说明: 请尽可能地优化你算法的时间和空间复杂度。

示例 1:

输入:
nums1 = [3, 4, 6, 5]
nums2 = [9, 1, 2, 5, 8, 3]
k = 5
输出:
[9, 8, 6, 5, 3]
示例 2:

输入:
nums1 = [6, 7]
nums2 = [6, 0, 4]
k = 5
输出:
[6, 7, 6, 0, 4]
示例 3:

输入:
nums1 = [3, 9]
nums2 = [8, 9]
k = 3
输出:
[9, 8, 9]
单调栈的做法

class Solution:
    def maxNumber(self, nums1: List[int], nums2: List[int], k: int) -> List[int]:
        def prep(nums,k):
            drop = len(nums)-k
            out=[]
            for num in nums:
                while drop and out and out[-1]<num:
                    out.pop()
                    drop -=1
                out.append(num)
            return out[:k]
        
        def merge(a,b):#a=[5,2,3],b=[3,4,5,6],输出:[5, 3, 4, 5, 6, 2, 3]
            return [max(a,b).pop(0) for _ in a+b]
                                 
        return max(merge(prep(nums1,i),prep(nums2,k-i))
                  for i in range(k+1)
                  if i <= len(nums1) and k-i <= len(nums2))

你可能感兴趣的:(刷题)