Loading。。。


算法题记录 35

20.有效的括号(简单)

给定一个只包括 ‘(‘,’)’,’{‘,’}’,’[‘,’]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

涉及知识点

解决思路

按规则出入栈,看是否能让栈为空。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def isValid(self, s: str) -> bool:
if len(s) % 2: # s 长度必须是偶数
return False
mp = {')': '(', ']': '[', '}': '{'}
st = []
for c in s:
if c not in mp: # c 是左括号
st.append(c) # 入栈
elif not st or st.pop() != mp[c]: # c 是右括号
return False # 没有左括号,或者左括号类型不对
return not st # 所有左括号必须匹配完毕

155.最小栈(中等)

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。

涉及知识点

解决思路

记录前缀最小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MinStack:
def __init__(self):
# 这里的 0 写成任意数都可以,反正用不到
self.st = [(0, inf)] # 栈底哨兵

def push(self, val: int) -> None:
self.st.append((val, min(self.st[-1][1], val)))

def pop(self) -> None:
self.st.pop()

def top(self) -> int:
return self.st[-1][0]

def getMin(self) -> int:
return self.st[-1][1]

394.字符串解码(中等)

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

涉及知识点

解决思路

利用栈来解决括号问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def decodeString(self, s: str) -> str:
stack, res, multi = [], "", 0
for c in s:
if c == '[':
stack.append([multi, res])
res, multi = "", 0
elif c == ']':
cur_multi, last_res = stack.pop()
res = last_res + cur_multi * res
elif '0' <= c <= '9':
multi = multi * 10 + int(c)
else:
res += c
return res

739.每日温度(中等)

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。

涉及知识点

解决思路

经典的栈的运用,单调栈。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
result=[0 for _ in range(len(temperatures))]
st=[(temperatures[0],0)]
for i in range(1,len(temperatures)):
while temperatures[i]>st[-1][0]:
result[st[-1][1]]=i-st[-1][-1]
st.pop()
if not st:
break
st.append((temperatures[i],i))
return result

84.柱状图中最大的矩形(困难)

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

涉及知识点

解决思路

单调栈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
n = len(heights)
left = [-1] * n
st = []
for i, x in enumerate(heights):
while st and x <= heights[st[-1]]:
st.pop()
if st:
left[i] = st[-1]
st.append(i)

right = [n] * n
st.clear()
for i in range(n - 1, -1, -1):
x = heights[i]
while st and x <= heights[st[-1]]:
st.pop()
if st:
right[i] = st[-1]
st.append(i)

ans = 0
for h, l, r in zip(heights, left, right):
ans = max(ans, h * (r - l - 1))
return ans

215.数组中的第K个最大元素(中等)

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

涉及知识点

解决思路

最小堆

1
2
3
4
5
6
7
8
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
nums2=[-i for i in nums]
heapq.heapify(nums2)
for i in range(k-1):
heapq.heappop(nums2)
return -heapq.heappop(nums2)

347.前K个高频元素(中等)

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

涉及知识点

解决思路

最小堆

1
2
3
4
5
6
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count=Counter(nums)
heap=[(val,key) for key,val in count.items()]
return [item[1] for item in heapq.nlargest(k,heap)]

295.数据流的中位数(困难)

中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。

例如 arr = [2,3,4] 的中位数是 3 。
例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5 。
实现 MedianFinder 类:

MedianFinder() 初始化 MedianFinder 对象。

void addNum(int num) 将数据流中的整数 num 添加到数据结构中。

double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。

涉及知识点

解决思路

用两个最小堆,left表示中位数左边的,right表示中位数右边的,更新时保持left与right长度相等或比right大1即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MedianFinder:
def __init__(self):
self.left = [] # 入堆的元素取相反数,变成最大堆
self.right = [] # 最小堆

def addNum(self, num: int) -> None:
if len(self.left) == len(self.right):
heappush(self.left, -heappushpop(self.right, num))
else:
heappush(self.right, -heappushpop(self.left, -num))

def findMedian(self) -> float:
if len(self.left) > len(self.right):
return -self.left[0]
return (self.right[0] - self.left[0]) / 2

121.买卖股票的最佳时机(简单)

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

涉及知识点

贪心

解决思路

因为只买卖一次,贪心即可。

1
2
3
4
5
6
7
8
9
class Solution:
def maxProfit(self, prices: List[int]) -> int:
ans = 0
min_price = prices[0]
for p in prices:
ans = max(ans, p - min_price)
min_price = min(min_price, p)
return ans

55.跳跃游戏(中等)

给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。

涉及知识点

贪心

解决思路

维护能摸到的最远距离即可。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def canJump(self, nums: List[int]) -> bool:
right=0
i=0
while i<=right:
right=max(right,nums[i]+i)
i+=1
if len(nums)-1<=right:
return True
return False

45.跳跃游戏2(中等)

给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。

每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

0 <= j <= nums[i]
i + j < n
返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。

涉及知识点

贪心

解决思路

每次跳转都只跳可以跳的最远距离。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution:
def jump(self, nums: List[int]) -> int:
if len(nums)==1:
return 0
count=0
right=0
i=0
tmp=0
while i<=right:
if nums[i]+i>right:
tmp=max(nums[i]+i,tmp)
if i==right:
right=tmp
tmp=i
count+=1
i+=1
if len(nums)-1<=right:
return count

763.划分字母区间(1443)

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。例如,字符串 “ababcc” 能够被分为 [“abab”, “cc”],但类似 [“aba”, “bcc”] 或 [“ab”, “ab”, “cc”] 的划分是非法的。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。

返回一个表示每个字符串片段的长度的列表。

涉及知识点

贪心

解决思路

本质是合并区间,不同字母出现在不同位置,按要求我们要在一个区间内包括所有某字母,比如a出现在0,2,6,8,那我们必须至少采取[0,8]这个区间,之所以说至少,是因为[0,8]里面可能有其它字母导致该区间被放得更大。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def partitionLabels(self, s: str) -> List[int]:
last = {c: i for i, c in enumerate(s)} # 每个字母最后出现的下标
ans = []
start = end = 0
for i, c in enumerate(s):
end = max(end, last[c]) # 更新当前区间右端点的最大值
if end == i: # 当前区间合并完毕
ans.append(end - start + 1) # 区间长度加入答案
start = i + 1 # 下一个区间的左端点
return ans

声明

题目均来源于leetcode公开题库,部分方法解析来源于高赞题解,如有不妥请联系。


文章作者: codeYu233
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 codeYu233 !
评论
  目录