记一下刷的题
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
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
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
给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。
示例:
输入:
[
[“1”,“0”,“1”,“0”,“0”],
[“1”,“0”,“1”,“1”,“1”],
[“1”,“1”,“1”,“1”,“1”],
[“1”,“0”,“0”,“1”,“0”]
]
输出: 6
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
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
给定一个仅包含小写字母的字符串,去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)。
示例 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:])
给定长度分别为 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))