继续leetcode刷题生涯
这里记录的都是笔者觉得有点意思的做法
参考了好几位大佬的题解,尤其是powcai大佬和labuladong大佬,感谢各位大佬
class Solution:
def removeInvalidParentheses1(self, s: str):
# 找字符串最长有效括号的长度
def longestVaildParentheses(s: str):
res = 0
stack = []
for a in s:
if a == "(":
stack.append("(")
elif a == ")":
if stack:
res += 2
stack.pop()
return res
# dfs
def helper(s, left_p, right_p, open, tmp):
# 当都小于0 都不满足条件
if left_p < 0 or right_p < 0 or open < 0:
return
# s剩余的括号都不够组成的
if s.count("(") < left_p or s.count(")") < right_p:
return
if not s:
# 输出
if left_p == 0 and right_p == 0 and open == 0:
res.add(tmp)
return
if s[0] == "(":
# 用 "("
helper(s[1:], left_p - 1, right_p, open + 1, tmp + "(")
# 不用 "("
helper(s[1:], left_p, right_p, open, tmp)
elif s[0] == ")":
# 用 ")"
helper(s[1:], left_p, right_p - 1, open - 1, tmp + ")")
# 不用 ")"
helper(s[1:], left_p, right_p, open, tmp)
else:
helper(s[1:], left_p, right_p, open, tmp + s[0])
l = longestVaildParentheses(s)
res = set()
# 因为l是最长的, 所以左括号和右括号各一半, 再用open表示左右括号抵消多少
helper(s, l // 2, l // 2, 0, "")
return list(res)
class NumArray:
def __init__(self, nums: List[int]):
self.dp = [0]
for num in nums:
self.dp.append(self.dp[-1] + num)
def sumRange(self, i: int, j: int) -> int:
return self.dp[j + 1] - self.dp[i]
class NumMatrix:
def __init__(self, matrix: List[List[int]]):
if not matrix or not matrix[0]:pass
else:
row = len(matrix)
col = len(matrix[0])
self.dp = [[ 0 ] * (col + 1) for _ in range(row + 1)]
for i in range(1, row + 1):
for j in range(1, col + 1):
self.dp[i][j] = matrix[i - 1][j - 1] + self.dp[i - 1][j] + self.dp[i][j - 1] - self.dp[i-1][j-1]
def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
return self.dp[row2 + 1][col2 + 1] - self.dp[row1][col2 + 1] - self.dp[row2 + 1][col1] + self.dp[row1][col1]
# 递归
class Solution:
def isAdditiveNumber(self, num: str) -> bool:
def isValid(sub1, sub2, num):
if not num: return True
sub1, sub2 = sub2, str(int(sub1) + int(sub2))
return num.startswith(sub2) and isValid(sub1, sub2, num[len(sub2):])
n = len(num)
for i in range(1, n // 2 + 1):
if num[0] == "0" and i > 1: return False
sub1 = num[:i]
for j in range(1, n):
# 剩下的长度都没有前面两个数最大长度长
if max(i, j) > n - i - j: break
if num[i] == "0" and j > 1: break
sub2 = num[i: i + j]
# 找到两个数, 看后面的数是否能引出来
if isValid(sub1, sub2, num[i + j:]): return True
return False
# 迭代
class Solution:
def isAdditiveNumber(self, num: str) -> bool:
def isValid(sub1, sub2, num):
while num:
sub1, sub2, = sub2, str(int(sub1) + int(sub2))
if not num.startswith(sub2): return False
num = num[len(sub2):]
return True
n = len(num)
for i in range(1, n // 2 + 1):
if num[0] == "0" and i > 1: return False
sub1 = num[:i]
for j in range(1, n):
# 剩下的长度都没有前面两个数最大长度长
if max(i, j) > n - i - j: break
if num[i] == "0" and j > 1: break
sub2 = num[i: i + j]
# 找到两个数, 看后面的数是否能引出来
if isValid(sub1, sub2, num[i + j:]): return True
return False
# 线段树
class NumArray:
def __init__(self, nums):
self.l = len(nums)
self.tree = [0] * self.l + nums
for i in range(self.l - 1, 0, -1):
self.tree[i] = self.tree[i << 1] + self.tree[i << 1 | 1]
def update(self, i, val):
n = self.l + i
self.tree[n] = val
while n > 1:
self.tree[n >> 1] = self.tree[n] + self.tree[n ^ 1]
n >>= 1
def sumRange(self, i, j):
m = self.l + i
n = self.l + j
res = 0
while m <= n:
if m & 1:
res += self.tree[m]
m += 1
m >>= 1
if n & 1 == 0:
res += self.tree[n]
n -= 1
n >>= 1
return res
# 动态规划
# dp[i][0]表示在i天买入最大利益
# dp[i][1]表示在i天卖出最大利益
# dp[i][2]表示在经过卖出的后一天冷冻期的最大利益
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if not prices: return 0
n = len(prices)
dp = [[0] * 3 for _ in range(n)]
dp[0][0] = -prices[0]
for i in range(1, n):
dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i])
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i])
dp[i][2] = dp[i - 1][1]
return dp[-1][1]
# 这个动态规划有点妙
# dfs 超时
class Solution:
def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
from collections import defaultdict
if not edges: return [0]
graph = defaultdict(list)
# 记录每个节点最高的高度
lookup = [0] * n
for x, y in edges:
graph[x].append(y)
graph[y].append(x)
def dfs(i, visited, depth):
lookup[i] = max(lookup[i], depth)
for j in graph[i]:
if j not in visited:
dfs(j, visited | {j}, depth + 1)
leaves = [i for i in graph if len(graph[i]) == 1]
for i in leaves:
dfs(i, {i}, 1)
min_num = min(lookup)
return [i for i in range(n) if lookup[i] == min_num]
# bfs
class Solution:
def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
from collections import defaultdict
if not edges: return [0]
graph = defaultdict(list)
for x, y in edges:
graph[x].append(y)
graph[y].append(x)
# 叶子节点,度为1
leaves = [i for i in graph if len(graph[i]) == 1]
while n > 2:
n -= len(leaves)
nxt_leaves = []
for leave in leaves:
# 与叶子节点相连的点找到
tmp = graph[leave].pop()
# 相连的点删去这个叶子节点
graph[tmp].remove(leave)
if len(graph[tmp]) == 1:
nxt_leaves.append(tmp)
leaves = nxt_leaves
return list(leaves)