当前位置:   article > 正文

leetcode-单调栈/单调队列_leetcode 单调队列

leetcode 单调队列

栈和队列都是为了保证元素的一种顺序性。(其实递归也是有顺序性的(运行到最后一步,再往前走),所以可用stack来模拟递归过程)

单调队列:队列的性质是先进先出,为什么滑动窗口的最大值这个题用单调递减队列?因为窗口往右边滑动的时候,队列前端的值不在窗口里了,把队列前端的值弹出。右侧的大值,一定可以屏蔽左侧的小值。

为什么862用单调递增队列?因为根据前缀和性质,用队列尾减去队列前,得到的就是这中间值之和,本质上是比较窗口的两端元素。

单调栈:栈的性质是先后进先出,为什么接雨水这个题用单调递减栈?因为需要比较的是相邻(不一定是挨着)的元素,而不是比较窗口两端元素。

规律:求s[i]的左边界和右边界。

力扣

目录

42 接雨水

84 柱状图的最大矩形

85 最大矩形

221 最大正方形

239 滑动窗口最大值

739. 每日温度

5614. 找出最具竞争力的子序列

678. 有效的括号字符串



42 接雨水

接雨水和柱形图最大面积,一个是凹槽,一个是凸起,凹槽是找左边的最大值和右边的最大值,所以不需要哨兵节点。凸起找左边的最小值和右边的最小值,需要哨兵节点。

接雨水问题(python实现单调栈问题)_meng_xin_true的博客-CSDN博客

代码随想录代码随想录PDF,代码随想录百度网盘,代码随想录知识星球,代码随想录八股文PDF,代码随想录刷题路线,代码随想录知识星球八股文https://programmercarl.com/0042.%E6%8E%A5%E9%9B%A8%E6%B0%B4.html#%E5%8D%95%E8%B0%83%E6%A0%88%E8%A7%A3%E6%B3%95

  1. class Solution(object):
  2. def trap(self, height):
  3. """
  4. :type height: List[int]
  5. :rtype: int
  6. """
  7. #维护一个单调递减栈
  8. ans=0
  9. stack=[]
  10. for i in range(len(height)):
  11. while len(stack) and height[i]>height[stack[-1]]:
  12. cur_index=stack.pop()
  13. if len(stack)==0:
  14. break
  15. left = height[stack[-1]]
  16. right = height[i]
  17. distans = i - stack[-1] -1
  18. cur_ans= (min(left,right)-height[cur_index])*distans
  19. ans=ans+cur_ans
  20. stack.append(i)
  21. return ans
  1. class Solution:
  2. def trap(self, height: List[int]) -> int:
  3. #单调递减栈。栈顶存储最小元素。
  4. #栈顶元素是凹槽,栈顶前一个元素是左边挡板,当前元素(如果比栈顶大),是右边挡板
  5. ans=0
  6. stack=[]
  7. for i in range(len(height)):
  8. #如果当前元素大于栈顶,当前元素是右挡板
  9. right=height[i]
  10. while stack and right>height[stack[-1]]:
  11. mid_index=stack.pop() #凹槽
  12. if not stack:
  13. break
  14. left=height[stack[-1]] #倒数第二个元素是左挡板
  15. h=min(left,right)-height[mid_index]
  16. w=i-stack[-1]-1
  17. cur_ans=h*w
  18. ans+=cur_ans
  19. stack.append(i)
  20. return ans

84 柱状图的最大矩形

接雨水和柱形图最大面积,一个是凹槽,一个是凸起,凹槽是找左边的最大值和右边的最大值,所以不需要哨兵节点。凸起找左边的最小值和右边的最小值,需要哨兵节点。

https://segmentfault.com/a/1190000022791301

单调递增栈。遍历数组,把数组下标放到stack中,如果当前元素小于stack的栈顶元素,弹出stack栈顶元素作为高度,宽度就是留守的Stack栈顶元素和当前元素下表的差值。

注意哨兵节点的使用。

  1. class Solution(object):
  2. def largestRectangleArea(self, heights):
  3. """
  4. :type heights: List[int]
  5. :rtype: int
  6. """
  7. size = len(heights)
  8. # 这里我们使用哨兵节点,这样就能够避免非空判断
  9. heights = [0] + heights+[0]
  10. # 数组长度发生了变化
  11. size += 2
  12. # 将哨兵先放入栈中
  13. stack = [0]
  14. ans = 0
  15. for i in range(1, size):
  16. # 与栈顶元素比较,进行判断是否要入栈
  17. # 出栈的逻辑
  18. while heights[i] < heights[stack[-1]]:
  19. cur_height = heights[stack.pop()]
  20. # 确定宽度
  21. cur_width = i - stack[-1] - 1
  22. ans = max(ans, cur_height * cur_width)
  23. stack.append(i)
  24. return ans
  1. class Solution(object):
  2. def largestRectangleArea(self, heights):
  3. """
  4. :type heights: List[int]
  5. :rtype: int
  6. """
  7. ans=0
  8. heights=[0]+heights+[0]
  9. stack=[]
  10. for i in range(len(heights)):
  11. while len(stack) and heights[i]<heights[stack[-1]]:
  12. cur_index=stack.pop()
  13. if len(stack)==0:
  14. break
  15. cur_height=heights[cur_index]
  16. distance=i-stack[-1]-1
  17. cur_ans=cur_height*distance
  18. ans=max(ans,cur_ans)
  19. stack.append(i)
  20. return ans

85 最大矩形

遍历每行,以每行为底边,可以看作是求最大柱状图的面积。

当这行中,元素为0的时候,柱状图列表为0,元素为1的时候,直接和上一行的进行累加。

  1. class Solution(object):
  2. def maxarea(self,height):
  3. stack=[]
  4. height=[0]+height+[0]
  5. ans=0
  6. for i in range(len(height)):
  7. while len(stack) and height[i]<height[stack[-1]]:
  8. cur_index=stack.pop()
  9. cur_height=height[cur_index]
  10. distnce=i-stack[-1]-1
  11. cur_ans=cur_height*distnce
  12. ans=max(ans,cur_ans)
  13. stack.append(i)
  14. return ans
  15. def maximalRectangle(self, matrix):
  16. """
  17. :type matrix: List[List[str]]
  18. :rtype: int
  19. """
  20. if len(matrix)==0:
  21. return 0
  22. res=0
  23. height=[0 for _ in range(len(matrix[0]))]
  24. for i in range(len(matrix)):
  25. cur=matrix[i]
  26. for j in range(len(cur)):
  27. if cur[j]=="1":
  28. height[j]=height[j]+1
  29. elif cur[j]=="0":
  30. height[j]=0
  31. print(height)
  32. cur_ans=self.maxarea(height)
  33. res=max(res,cur_ans)
  34. return res

221 最大正方形

最大矩形加一行代码。在计算面积的时候限制一下distance和height的大小。

  1. class Solution(object):
  2. def maxarea(self,height):
  3. stack=[]
  4. height=[0]+height+[0]
  5. ans=0
  6. for i in range(len(height)):
  7. while len(stack) and height[i]<height[stack[-1]]:
  8. cur_index=stack.pop()
  9. cur_height=height[cur_index]
  10. distnce=i-stack[-1]-1
  11. if distnce>=cur_height:
  12. cur_ans=cur_height*cur_height
  13. ans=max(ans,cur_ans)
  14. stack.append(i)
  15. return ans
  16. def maximalSquare(self, matrix):
  17. """
  18. :type matrix: List[List[str]]
  19. :rtype: int
  20. """
  21. if len(matrix)==0:
  22. return 0
  23. res=0
  24. height=[0 for _ in range(len(matrix[0]))]
  25. for i in range(len(matrix)):
  26. cur=matrix[i]
  27. for j in range(len(cur)):
  28. if cur[j]=="1":
  29. height[j]=height[j]+1
  30. elif cur[j]=="0":
  31. height[j]=0
  32. print(height)
  33. cur_ans=self.maxarea(height)
  34. res=max(res,cur_ans)
  35. return res

239 滑动窗口最大值

暴力解法,时间复杂度o(nk).超时。

  1. class Solution(object):
  2. def maxSlidingWindow(self, nums, k):
  3. """
  4. :type nums: List[int]
  5. :type k: int
  6. :rtype: List[int]
  7. """
  8. res=[]
  9. for i in range(len(nums)-k+1):
  10. left=i
  11. right=i+k
  12. cur_max=nums[left]
  13. for j in range(left+1,right):
  14. cur_max=max(cur_max,nums[j])
  15. res.append(cur_max)
  16. return res

单调队列

空间换时间,时间复杂度o(n)

力扣

  1. import collections
  2. #单调递减队列
  3. class Solution:
  4. def maxSlidingWindow(self, nums, k):
  5. if not nums or k == 0: return []
  6. deque = collections.deque()
  7. for i in range(k):
  8. #前一个数字,小于当前数字。把前一个数字弹出
  9. while deque and deque[-1] < nums[i]:
  10. deque.pop()
  11. deque.append(nums[i])
  12. print(deque)
  13. res = [deque[0]]
  14. #i表示滑动窗口最右边
  15. for i in range(k, len(nums)):
  16. #如果队列头部值,是上一个窗口的值,就弹出去。
  17. if deque[0] == nums[i - k]:
  18. deque.popleft()
  19. while deque and deque[-1] < nums[i]:
  20. deque.pop()
  21. deque.append(nums[i])
  22. res.append(deque[0])
  23. print(i,res,deque)
  24. return res
  25. nums=[2,3,4,2,6,2,5,1]
  26. k=3
  27. result=Solution().maxSlidingWindow(nums,k)
  28. print(result)

739. 每日温度

  1. class Solution:
  2. def dailyTemperatures(self, T: List[int]) -> List[int]:
  3. stack = []
  4. res = [0] * len(T)
  5. for i in range(len(T)):
  6. while stack and T[stack[-1]] < T[i]:
  7. res[stack[-1]] = i - stack[-1]
  8. stack.pop()
  9. stack.append(i)
  10. return res
  11. 作者:xiao-xue-66
  12. 链接:https://leetcode-cn.com/problems/daily-temperatures/solution/pythonti-jie-dan-diao-di-jian-zhan-by-xiao-xue-66/
  13. 来源:力扣(LeetCode)
  14. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  1. class Solution(object):
  2. def dailyTemperatures(self, T):
  3. """
  4. :type T: List[int]
  5. :rtype: List[int]
  6. """
  7. #单调递减栈
  8. stack=[]
  9. res=[0 for _ in range(len(T))]
  10. for i in range(len(T)):
  11. while len(stack) and T[stack[-1]]<T[i]:
  12. cur_index=stack.pop()
  13. cur_res=i-cur_index
  14. res[cur_index]=cur_res
  15. stack.append(i)
  16. return res

5614. 找出最具竞争力的子序列

 https://leetcode-cn.com/problems/find-the-most-competitive-subsequence/solution/python3-shuang-bai-jie-fa-by-ni-jiao-wo-dpma/

  1. class Solution(object):
  2. def mostCompetitive(self, nums, k):
  3. """
  4. :type nums: List[int]
  5. :type k: int
  6. :rtype: List[int]
  7. """
  8. #维护一个单调递增栈
  9. stack=[]
  10. n=len(nums)
  11. for i in range(n):
  12. while len(stack) and stack[-1]>nums[i] and (n-i-1)>= k-len(stack):
  13. stack.pop()
  14. stack.append(nums[i])
  15. return stack[:k]

678. 有效的括号字符串

力扣

 题解:开始的是我是用的,在一开始,我只是单纯的记录左右括号数量的差值和星的个数。这样做忽略了第三个条件。

要在栈里记录位置信息。

先看一下我最开始的题解

  1. class Solution(object):
  2. def checkValidString(self, s):
  3. """
  4. :type s: str
  5. :rtype: bool
  6. """
  7. stack=[]
  8. cnt=0
  9. for i in range(len(s)):
  10. cur=s[i]
  11. if cur=='(':
  12. stack.append(cur)
  13. elif cur==')':
  14. if len(stack)==0:
  15. #用星号模拟左括号
  16. if cnt>0:
  17. cnt=cnt-1
  18. else:
  19. stack.pop()
  20. elif cur=="*":
  21. cnt=cnt+1
  22. if len(stack)==0:
  23. return True
  24. #用星号模拟右括号
  25. if len(stack)==cnt:
  26. return True
  27. return False
  1. class Solution(object):
  2. def checkValidString(self, s):
  3. """
  4. :type s: str
  5. :rtype: bool
  6. """
  7. stack=[]
  8. stack_star=[]
  9. cnt=0
  10. for i in range(len(s)):
  11. cur=s[i]
  12. if cur=='(':
  13. stack.append(i)
  14. elif cur==')':
  15. if len(stack)==0:
  16. #用星号模拟左括号
  17. if len(stack_star)>0:
  18. stack_star.pop()
  19. else:
  20. return False
  21. else:
  22. stack.pop()
  23. elif cur=="*":
  24. stack_star.append(i)
  25. if len(stack)==0:
  26. return True
  27. #stack不为空的时候
  28. while stack:
  29. if not stack_star:
  30. return False
  31. elif stack[-1]>stack_star[-1]:
  32. return False
  33. else:
  34. stack.pop()
  35. stack_star.pop()
  36. return True

32. 最长有效括号

  1. //最长的有效括号--------------->括号子串,括号子串的结尾一定是')',根据右括号为右端点去寻找合法的最长子串对应的左括号
  2. //只包含'('和')'
  3. public int longestValidParentheses(String s) {
  4. int n = s.length(), maxLen = 0;
  5. Deque<Integer> stack = new ArrayDeque<>();
  6. stack.push(-1);
  7. for (int i = 0; i < n; i++) {
  8. char ch = s.charAt(i);
  9. // 如果是左括号直接入栈即可
  10. if (ch == '(')
  11. stack.push(i);
  12. else {
  13. // 如果是右括号,存在两种情况
  14. // 1.如果前面可以有左括号和它进行匹配,那么就存在一个由左括号、右括号组成的子串
  15. // 2.如果前面没有左括号和它进行匹配,那么这个右括号就形成了新的边界。新的子串匹配时,起点必须在该边界右边
  16. if (stack.size() == 1) {
  17. // 如果栈的大小为1,说明只存放了边界
  18. // 说明存放的内容为:边界
  19. // 相应的做法为边界替换,将旧的边界出栈,然后放入新的边界
  20. // 说明该右括号找不到和它可以匹配的左括号,那么该子串长度无效。同时这个右括号形成了新的边界(参照物)
  21. stack.pop();
  22. stack.push(i);
  23. } else {
  24. // 如果栈的大小不为1
  25. // 说明存放的内容为:边界+左括号索引+左括号索引+左括号索引......
  26. // 说明可以找到和它进行匹配的左括号
  27. stack.pop();
  28. maxLen = Math.max(maxLen,i-stack.peek());
  29. }
  30. }
  31. }
  32. return maxLen;
  33. }
  34. 2
  35. 查看 1 条回复
  36. 回复

907. 子数组的最小值之和

 单调栈+组合数学

力扣

496. 下一个更大元素 I

 力扣

单调递减栈

  1. class Solution(object):
  2. def nextGreaterElement(self, nums1, nums2):
  3. """
  4. :type nums1: List[int]
  5. :type nums2: List[int]
  6. :rtype: List[int]
  7. """
  8. #找右的下一个更大元素,从后往前遍历,维护一个单调递减栈
  9. #为什么要从后往前遍历,因为是要找右侧,只有从后往前遍历才能比较到当前元素和右侧元素
  10. #先用单调递减栈找到nums2的下一个更大元素
  11. stack=[]
  12. next_max=[-1 for _ in range(len(nums2))]
  13. for i in range(len(nums2)-1,-1,-1):
  14. #判断当前元素和右侧元素(右侧元素存储在单调栈中,栈顶是挨着最近的)
  15. while stack and nums2[i]>stack[-1]:
  16. stack.pop()
  17. if stack and nums2[i]<stack[-1]:
  18. next_max[i]=stack[-1]
  19. stack.append(nums2[i])
  20. res=[]
  21. for i in range(len(nums1)):
  22. num=nums1[i]
  23. num_index=nums2.index(num)
  24. cur_ans=next_max[num_index]
  25. res.append(cur_ans)
  26. return res

503. 下一个更大元素 II

环形数组+单调递减栈

力扣

  1. class Solution(object):
  2. def nextGreaterElements(self, nums):
  3. """
  4. :type nums: List[int]
  5. :rtype: List[int]
  6. """
  7. #用取模来模拟环形数组
  8. stack=[]
  9. n=len(nums)
  10. res=[-1 for _ in range(len(nums))]
  11. for i in range(n*2-1,-1,-1):
  12. #如果当前元素大于栈顶元素
  13. while stack and nums[i%n]>=stack[-1]:
  14. stack.pop()
  15. if stack and nums[i%n]<stack[-1]:
  16. res[i%n]=stack[-1]
  17. stack.append(nums[i%n])
  18. return res

2104. 子数组范围和

这个题是找的下一个更大/更小元素,和最大宽度坡不一样,最大宽度坡找的不是下一个更大/更小元素。

 计算 右侧比5小的第一个数,从右往左遍历,单调递增栈。

入栈:[2],1比2小,2出栈,1入栈[1],4入栈,[1,4],7入栈,[1,4,7],6比7小,7出栈,6入栈,[1,4,6]

为什么是单调递增栈?因为要求的是右边第一个比cur小的数,假设右侧j小于i,i出栈,j入栈,假如i比cur小,那么j也一定比cur小,j更靠近cur,所以可用小数屏蔽大数。

 力扣

 力扣

  1. class Solution:
  2. def subArrayRanges(self, nums: List[int]) -> int:
  3. # nums[i]是多少子数组的最大值,以及多少子数组的最小值。相加
  4. # 求nums[i]是多少子数组的最大值,找到nums[i]左边和右边的边界,2个单调栈
  5. # 求nums[i]是多少子数组的最小值,找到nums[i]左边和右边的边界,2个单调栈。共4个单调栈
  6. left_max = [-1 for i in range(len(nums))]
  7. right_max = [-1 for i in range(len(nums))]
  8. left_min = [-1 for i in range(len(nums))]
  9. right_min = [-1 for i in range(len(nums))]
  10. # 最大值,往右边可以辐射到哪里,单调递减栈
  11. stack = []
  12. for i in range(len(nums) - 1, -1, -1):
  13. while stack and nums[i] > nums[stack[-1]]:
  14. stack.pop()
  15. #当前元素比stack[-1]小,说明从stack[-1]开始已经不是最大值了,右边的边界就是stack[-1]
  16. if stack and nums[i] <= nums[stack[-1]]:
  17. right_max[i] = stack[-1]
  18. else:
  19. right_max[i] = len(nums)
  20. stack.append(i)
  21. # 最大值,往左边可以辐射到哪里,单调递减栈
  22. stack = []
  23. for i in range(len(nums)):
  24. while stack and nums[i] >= nums[stack[-1]]:
  25. stack.pop()
  26. # 当前元素比stack[-1]小,说明从stack[-1]开始已经不是最大值了,右边的边界就是stack[-1]
  27. if stack and nums[i] < nums[stack[-1]]:
  28. left_max[i] = stack[-1]
  29. else:
  30. left_max[i] = -1
  31. stack.append(i)
  32. # 最小值,往右边可以辐射到哪里,单调递递增
  33. stack = []
  34. for i in range(len(nums) - 1, -1, -1):
  35. while stack and nums[i] < nums[stack[-1]]:
  36. stack.pop()
  37. # 当前元素比stack[-1]大,说明从stack[-1]开始已经不是最小值了,右边的边界就是stack[-1]
  38. if stack and nums[i] >= nums[stack[-1]]:
  39. right_min[i] = stack[-1]
  40. else:
  41. right_min[i] = len(nums)
  42. stack.append(i)
  43. # 最小值,往左边边可以辐射到哪里,单调递增
  44. stack = []
  45. for i in range(len(nums)):
  46. while stack and nums[i] <= nums[stack[-1]]:
  47. stack.pop()
  48. # 当前元素比stack[-1]大,说明从stack[-1]开始已经不是最小值了,左边的边界就是stack[-1]
  49. if stack and nums[i] > nums[stack[-1]]:
  50. left_min[i] = stack[-1]
  51. else:
  52. left_min[i] = -1
  53. stack.append(i)
  54. print(left_max)
  55. print(right_max)
  56. print(left_min)
  57. print(right_min)
  58. ans = 0
  59. for i in range(len(nums)):
  60. ans += nums[i] * (i - left_max[i]) * (right_max[i] - i)
  61. ans -= nums[i] * (i - left_min[i]) * (right_min[i] - i)
  62. return ans

962. 最大宽度坡

贪心+单调栈

左边界尽可能靠左,右边界尽可能靠右。

左边界尽可能靠左,所以单调递减栈从0下标开始。

右边界尽可能靠右,所以从右往左遍历

 

 

  1. class Solution:
  2. def maxWidthRamp(self, A: List[int]) -> int:
  3. stack = []
  4. n = len(A)
  5. for i in range(n):
  6. if not stack or A[stack[-1]] > A[i]:
  7. stack.append(i)
  8. res = 0
  9. i = n - 1
  10. while i > res: # 当res大于等于i时没必要继续遍历了
  11. while stack and A[stack[-1]] <= A[i]:
  12. res = max(res, i - stack[-1])
  13. stack.pop()
  14. i -= 1
  15. return res
  16. 作者:Elmer
  17. 链接:https://leetcode-cn.com/problems/maximum-width-ramp/solution/dan-diao-zhan-python-yi-kan-jiu-dong-by-elmer/
  18. 来源:力扣(LeetCode)
  19. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1124. 表现良好的最长时间段

  1. class Solution:
  2. def longestWPI(self, hours: List[int]) -> int:
  3. n = len(hours)
  4. score = [1 if h >8 else -1 for h in hours]
  5. presum = [0] * (n + 1)
  6. for i in range(1, n+1):
  7. presum[i] = presum[i-1] + score[i-1]
  8. stack = []
  9. for i in range(n+1):
  10. if not stack or presum[stack[-1]] > presum[i]:
  11. stack.append(i)
  12. ans = 0
  13. i = n
  14. while i > ans:
  15. while stack and presum[stack[-1]] < presum[i]:
  16. ans = max(ans, i - stack.pop())
  17. i -= 1
  18. return ans
  19. 作者:shzi
  20. 链接:https://leetcode-cn.com/problems/longest-well-performing-interval/solution/dan-diao-zhan-by-shzi/
  21. 来源:力扣(LeetCode)
  22. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  1. class Solution:
  2. def longestWPI(self, hours: List[int]) -> int:
  3. #前缀和求出来当前i以及以前,劳累的天数是不是严格大于不劳累的天数
  4. #如果不把presum的长度+1,那么要计算j到i之间的天数,应该是presum[i]-presum[j-1],不好处理边界
  5. #为什么是presum[i]-presum[j-1],而不是presum[i]-presum[j],因为要求的区间包括j,要从j的前一位开始减。
  6. n = len(hours)
  7. score = [1 if h >8 else -1 for h in hours]
  8. presum = [0] * (n + 1)
  9. for i in range(1, n+1):
  10. presum[i] = presum[i-1] + score[i-1]
  11. print(presum)
  12. #presum[i] - presum[j] > 0,表示「劳累的天数」是严格 大于「不劳累的天数」
  13. #j小于i且presum[j]小于presum[i],变成了962
  14. #单调递减栈
  15. stack=[]
  16. for i in range(len(presum)):
  17. if not stack or presum[i] < presum[stack[-1]]:
  18. stack.append(i)
  19. print(stack)
  20. res=0
  21. for i in range(len(presum)-1,-1,-1):
  22. while stack and presum[i] > presum[stack[-1]]:
  23. res=max(res,i-stack[-1])
  24. stack.pop()
  25. return res

2334. 元素值大于变化阈值的子数组

 

计算器

力扣

224. 基本计算器

 双栈

  1. class Solution(object):
  2. def calculate(self, s):
  3. """
  4. :type s: str
  5. :rtype: int
  6. """
  7. #去掉空格
  8. s = s.replace(" ","")
  9. from collections import deque
  10. # 运算符号优先级
  11. hashmap = {'-': 1,
  12. '+': 1,
  13. '*': 2,
  14. '/': 2,
  15. '%': 2,
  16. '^': 3,
  17. }
  18. # 存放所有数字
  19. nums = deque([0]) # 为了防止第一个数为负数,先往nums加个0
  20. # 存放所有的操作
  21. ops = deque([])
  22. def calc(nums, ops):
  23. if not nums or len(nums) < 2 or not ops:
  24. return
  25. b, a = nums.pop(), nums.pop()
  26. op = ops.pop()
  27. ans = 0
  28. if op == '+':
  29. ans = a + b
  30. elif op == '-':
  31. ans = a - b
  32. elif op == '*':
  33. ans = a * b
  34. elif op == '/':
  35. ans = a // b
  36. elif op == '^':
  37. ans = int(pow(a, b))
  38. elif op == '%':
  39. ans = a % b
  40. nums.append(ans)
  41. n = len(s)
  42. i = 0
  43. while i < n:
  44. c = s[i]
  45. #左括号入栈ops
  46. if c == '(':
  47. ops.append(c)
  48. #右括号计算
  49. elif c == ')':
  50. while ops:
  51. if ops[-1] != '(':
  52. calc(nums, ops)
  53. else:
  54. ops.pop()
  55. break
  56. else:
  57. #如果是数字,入栈nums
  58. if c.isdigit():
  59. tmp = c
  60. j = i + 1
  61. #比如几位连在一起的,“150”
  62. while j < n and s[j].isdigit():
  63. tmp += s[j]
  64. j += 1
  65. nums.append(int(tmp))
  66. i = j - 1
  67. else:
  68. #处理特殊case,如果当前是,加号或者减号,但是前面不是数字的时候
  69. if i > 0 and s[i - 1] in '(+-':
  70. nums.append(0)
  71. #如果是 加号,或者减号
  72. while ops and ops[-1] != '(':
  73. #前一位如果小于等于当前的运算优先级,就计算出来。
  74. #例子:s="2-1+2"
  75. prev = ops[-1]
  76. if hashmap[prev] >= hashmap[c]:
  77. calc(nums, ops)
  78. else:
  79. break
  80. ops.append(c)
  81. i += 1
  82. while ops and ops[-1] != '(':
  83. calc(nums, ops)
  84. return nums[-1]

6202. 使用机器人打印字典序最小的字符串

 

  1. class Solution:
  2. def robotWithString(self, s: str) -> str:
  3. ans = []
  4. cnt = Counter(s)
  5. min = 0 # 剩余最小字母
  6. st = []
  7. for c in s:
  8. cnt[c] -= 1
  9. while min < 25 and cnt[ascii_lowercase[min]] == 0:
  10. min += 1
  11. st.append(c)
  12. while st and st[-1] <= ascii_lowercase[min]:
  13. ans.append(st.pop())
  14. return ''.join(ans)
  15. 作者:endlesscheng
  16. 链接:https://leetcode.cn/problems/using-a-robot-to-print-the-lexicographically-smallest-string/solution/tan-xin-zhan-by-endlesscheng-ldds/
  17. 来源:力扣(LeetCode)
  18. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/233586?site
推荐阅读
相关标签
  

闽ICP备14008679号