1021. Remove Outermost Parentheses
删除最外层的括号。原题
1 | Input: "(()())(())" |
方法一:比赛时的丑陋写法。使用索引记录位置坐切片。
1 | def removeOuterParentheses(self, S: str) -> str: |
1 | def removeOuterParentheses(self, S: str) -> str: |
1047. Remove All Adjacent Duplicates In String
每两个相邻的相同字符串可以消掉。类似于连连看。原题
1 | def removeDuplicates(self, S: str) -> str: |
1172. Dinner Plate Stacks
有这样一堆栈,每个栈有个容量,可以在指定索引下删除某个栈,每次push时需要在最左的不满的栈。原题
1 | Input: |
方法一:一开始被题吓到了,竞赛时没做出来,核心思想在于维护一个堆,记录不满的栈。以便插入时可以找到该索引。
class DinnerPlates:
1 | def __init__(self, capacity: int): |
901. Online Stock Span
实时找出数据流中连续的比不大于当前值的个数。原题
1 | Input: ["StockSpanner","next","next","next","next","next","next","next"], [[],[100],[80],[60],[70],[60],[75],[85]] |
方法一:<=
可以累加。
1 | class StockSpanner: |
907. Sum of Subarray Minimums
一个数组所有子数组的最小值的和。
1 | Input: [3,1,2,4] |
方法一:by@Lee, 没想到可以用stack,实际上和901问题是一样的,对于一个数而言,找到左侧和右侧比它大的数,代表着左侧和右侧所能组成的子数组的长度,就是它在最小值计算里出现的次数。本来想封装一下这个方法,但是计算左侧时条件是>
,其实终点不在于顺序,而是=只能有一个,因为如果都按>=
计算,相同数字的就会有子数组计算重复了。
1 | def sumSubarrayMins(self, A: List[int]) -> int: |
方法二:Lee又将它写成了一次遍历的形式。
1 | def sumSubarrayMins(self, A): |
1299. Replace Elements with Greatest Element on Right Side
根据数组重新生成一个数组,每个元素对应原数组右侧最大的数字。原题
1 | Input: arr = [17,18,5,4,6,1] |
方法一:栈
1 | def replaceElements(self, arr: List[int]) -> List[int]: |
1 | def replaceElements(self, arr: List[int], mx=-1) -> List[int]: |
1249. Minimum Remove to Make Valid Parentheses
删除字符串中多余的括号。原题
1 | Input: s = "lee(t(c)o)de)" |
方法一:比较笨的方法,遍历了两次。
1 | def minRemoveToMakeValid(self, s: str) -> str: |
方法二:stack、这个方法有点不好理解, 最后的while 循环时为了防止末尾有过多的(
1 | def minRemoveToMakeValid(self, s: str) -> str: |
1190. Reverse Substrings Between Each Pair of Parentheses
将括号内的字符串反转。原题
1 | Input: s = "(u(love)i)" |
方法一:用了和1249一样的解法。
1 | def reverseParentheses(self, s: str) -> str: |
1209. Remove All Adjacent Duplicates in String II
将字符串中连续的k的字母全部删除,返回剩余的字符串。原题
1 | Input: s = "abcd", k = 2 |
方法一:这道题虽然ac了,但是复杂度太高了。
1 | def removeDuplicates(self, s: str, k: int) -> str: |
1 | def removeDuplicates(self, s: str, k: int) -> str: |
1475. Final Prices With a Special Discount in a Shop
找出数组中后面元素比当前元素小的差。原题
1 | Input: prices = [8,4,6,2,3] |
方法一:暴力法。
1 | def finalPrices(self, prices: List[int]) -> List[int]: |
1 | def finalPrices(self, A: List[int]) -> List[int]: |
739. Daily Temperature
找出比当前元素之后的大的值,计算索引差,没有则是0。原题
方法一:刚刚做完1475的题,一样的解法。
1 | def dailyTemperatures(self, T: List[int]) -> List[int]: |
394. Decode String
就是根据括号来重复字符串。原题
1 | Input: s = "3[a]2[bc]" |
方法一:使用了两个栈,分别存储数字和字母。
1 | def decodeString(self, s: str) -> str: |
方法二:使用一个stack,因为这个规律是有保证的,左括号前一定是数字。
1 | def decodeString(self, s: str) -> str: |
1541. Minimum Insertions to Balance a Parentheses String
平衡一个括号对,最少需要插入多少次,括号对为一个(对应2个)。原题
1 | Input: s = "(()))" |
方法一:比赛时卡住了。这是Lee215的解法。想到了用栈和这种方式,但是没想好如何内部处理。
1 | def minInsertions(self, s: str) -> int: |
856. Score of Parentheses
括号的分数,根据规则计算括号的分数。()
表示1分;AB表示A+B,(A)
表示A*2。原题
1 | Input: "()" |
方法一:首次AC的方法。
1 | def scoreOfParentheses(self, S: str) -> int: |
方法二:Lee的方法太盖了,但是不知道咋想的,这个思路的过程我还是没想明白。
1 | def scoreOfParentheses(self, S: str) -> int: |
方法三:O(1)space的方法,同样牛逼。
1 | def scoreOfParentheses(self, S): |
方法四:这个方法倒是没想到。
1 | def scoreOfParentheses(self, S): |
面试题 08.06. 汉诺塔问题
经典的汉诺塔问题,一个三个柱子,将盘子从A移动到C。
方法一:分治思想。
n = 1 时,直接把盘子从 A 移到 C;
n > 1 时,
先把上面 n - 1 个盘子从 A 移到 B(子问题,递归);
再将最大的盘子从 A 移到 C;
再将 B 上 n - 1 个盘子从 B 移到 C(子问题,递归)。
1 | def hanota(self, A: List[int], B: List[int], C: List[int]) -> None: |
316. Remove Duplicate Letters
移除重复的字符,保证最后结果是字典序最小的。
1 | Input: s = "bcabc" |
方法一:使用stack来辅助判断。Lee的方法。
1 | def removeDuplicateLetters(self, s: str) -> str: |
503. Next Greater Element II
下一个比当前元素大的元素,数组首位连接。原题
和1030题相似。方法一:首位连接,所以要遍历两次。
1 | def nextGreaterElements(self, nums: List[int]) -> List[int]: |
1 | def nextGreaterElements(self, nums: List[int]) -> List[int]: |
946. Validate Stack Sequences
给定一个入栈和出栈的顺序,判断是否最后可以清空该栈。原题
1 | Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1] |
1 | def validateStackSequences(self, pushed: 'List[int]', popped: 'List[int]') -> 'bool': |
735. Asteroid Collision
行星碰撞,在一个横轴上有些数字表示行星的质量,正负表示方向,所有的行星以相同的速度运行,两个行星碰撞后质量小的会消失,相同则都消失,问最后剩余的行星。
1 | Input: asteroids = [5,10,-5] |
方法一:很容易想到stack来解决,15分钟AC,需要注意内部也需要使用循环,因为有[10, 1, -5]
这种情况,所以需要内循环不停地比较和碰撞。自认为比最高票答案写得简洁一些。
1 | def asteroidCollision(self, asteroids: List[int]) -> List[int]: |
456. 132 Pattern
是否有子序列是13,2的模式,即存在i<j<k,nums[i]<nums[j]<nums[k]
1 | Input: nums = [1,2,3,4] |
方法一:栈,挺难想的,看了答案才明白。third表示在当前值之后的小于当前数中最大的一个。
1 | def find132pattern(self, nums: List[int]) -> bool: |
1673. Find the Most Competitive Subsequence
找到一个长度为k的最小的子序列。
1 | Input: nums = [3,5,2,6], k = 2 |
方法一:竞赛时用了一个比较暴力+tricky方法过了5000个0的case。这题有些贪心的思想在里。
1 | def mostCompetitive(self, nums: List[int], k: int) -> List[int]: |
84. Largest Rectangle in Histogram
柱形图里最大的矩形面积。
1 | Input: [2,1,5,6,2,3] |
方法一:单调栈,维护一个单调递增的栈,出栈时计算此高度的最大宽度,从而得出面积。一个难想的地方在于,这里每次出栈都更新一次结果。栈初始化为[-1]和尾部添0是一套操作,避免特殊情况的判断。
1 | def largestRectangleArea(self, heights: List[int]) -> int: |
895. Maximum Frequency Stack
最大频率栈,每次返回频率最多的数。
1 | Input: |
方法一:这题的关键是要想明白数据冗余。每个频率上都保存一次数据。
1 | class FreqStack: |
1776. Car Fleet II
车队,同853很像,区别在于求每辆车和前面车相撞的时间。
1 | Input: cars = [[1,2],[2,1],[4,3],[7,2]] |
方法一:比赛时没有解出来,这是Lee的答案
1 | def getCollisionTimes(self, A: List[List[int]]) -> List[float]: |
150. Evaluate Reverse Polish Notation
计算逆波兰表达式。
1 | Input: tokens = ["2","1","+","3","*"] |
方法一:提本身不难,Python有2个坑。一个是isdigit("-1")
居然返回False。另一个是6//-13
值为-1
是向下取整。这和golang表现不一样。golang会输出0.
1 | def evalRPN(self, tokens: List[str]) -> int: |
224. Basic Calculator
实现一个计算带有括号的,只包含+-的算式。
1 | Input: s = "(1+(4+5+2)-3)+(6+8)" |
方法一:栈,sign初始化2个1,是因为本身算式算一个+,如果是左括号开头又算一个+。这里我想到的差了一个1.
1 | def calculate(self, s: str) -> int: |
1856. Maximum Subarray Min-Product
找到子数组,使得子数组的和与最小值的积最大。
1 | Input: nums = [1,2,3,2] |
方法一:比赛时思路对了,没有写出代码,其实枚举最小值就行,然后通过前缀和来找到,对于这个最小值,最侧第一个比它小的,和右侧第一个比它小的。使用单调递增栈来实现。
1 | def maxSumMinProduct(self, nums: List[int]) -> int: |
1944. Number of Visible People in a Queue
右侧可以看见多少个人,可以看到比自己矮的。
1 | Input: heights = [10,6,8,5,11,9] |
方法一:比赛的时候想到单调栈,但是不知道怎么写,这是比较简单的题了。1
2
3
4
5
6
7
8
9
10
11
12
13def canSeePersonsCount(self, heights: List[int]) -> List[int]:
N = len(heights)
res = [0] * N
stack = []
for i in range(N-1, -1, -1):
while stack:
res[i] += 1
if heights[i] > heights[stack[-1]]:
stack.pop()
else:
break
stack.append(i)
return res