leetcode热题100在之前的分类总结中已经完成了一部分,现在完成剩下的一部分问题
https://leetcode-cn.com/problems/decode-string/
class Solution:
def decodeString(self, s: str) -> str:
'''
栈操作,栈中存入左括号前的数字与两个左括号中间的字符串,遇到右括号出栈
'''
stack = []
res = ''
num = 0
for i in range(len(s)):
# 数字转换格式
if '0'<=s[i]<='9':
num = num * 10 + int(s[i])
# print(num)
# 遇到左括号,栈中存入,此括号前的字符串与数字
elif s[i] == '[':
stack.append((res, num))
res, num = '', 0
# 遇到右括号出栈
elif s[i] == ']':
# last_res是一个左括号与上一个左括号中间的字符串
last_res, num_ = stack.pop()
# print(last_res, res, num_)
res = last_res + num_ * res
# res表示左括号与右括号中间的字符串
else:
res += s[i]
return res
https://leetcode-cn.com/problems/evaluate-division/
class Solution:
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
'''
构建一个带权图,如果x/y = v,那么x到y的权值为v,y到x的权值为1/v
最终对于求解的每一个方程式,只需要找出特定的路径,然后将权值相乘
'''
# 采用dict的方式构建图
graph = {}
for (x, y), v in zip(equations, values):
if x in graph:
graph[x][y] = v
else:
graph[x] = {y:v}
if y in graph:
graph[y][x] = 1/v
else:
graph[y] = {x: 1/v}
#dfs进行路径的查找
def helper(s, t):
if s not in graph: return -1
if s == t: return 1
for node in graph[s].keys():
if node == t: return graph[s][node]
else:
if node not in visited:
visited.add(node)
v = helper(node, t)
if v == -1: continue
else: return graph[s][node]*v
return -1
res = []
for x, y in queries:
visited = set()
v = helper(x, y)
res.append(v)
return res
class WeightUnionFindSet:
def __init__(self):
self.parent = {} # 存放父亲节点
self.parent_div_cur = {} # 存放父亲节点除以自己的商
def union(self, x, y, x_div_y):
# 增加新节点
if x not in self.parent:
self.parent[x] = x
self.parent_div_cur[x] = 1.0
if y not in self.parent:
self.parent[y] = y
self.parent_div_cur[y] = 1.0
# 寻找祖宗节点
root_x, root_x_div_x = self.find_root(x)
root_y, root_y_div_y = self.find_root(y)
# 祖宗不同则进行合并
if (root_x != root_y):
self.parent[root_y] = root_x
self.parent_div_cur[root_y] = root_x_div_x / root_y_div_y * x_div_y
# root_x / root_y = root_x / x / (root_y / y) * (x / y)
def find_root(self, x):
if self.parent[x] == x:
return x, self.parent_div_cur[x]
else:
# 找到祖宗以及祖宗除以当前父节点的商
root, root_div_parent = self.find_root(self.parent[x])
# 路径压缩,并得到祖宗除以当前节点的商
self.parent[x] = root
self.parent_div_cur[x] = root_div_parent * self.parent_div_cur[x]
return self.parent[x], self.parent_div_cur[x]
def x_div_y(self, x, y):
# x / y = root_y / y / (root_x / x)
if x not in self.parent or y not in self.parent:
return -1
else:
root_x, root_x_div_x = self.find_root(x)
root_y, root_y_div_y = self.find_root(y)
if root_x != root_y:
return -1
else:
return root_y_div_y / root_x_div_x
class Solution:
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
weight_union_find_set = WeightUnionFindSet()
# 加入并查集
for (x, y), x_div_y in zip(equations, values):
weight_union_find_set.union(x, y, x_div_y)
# 查询并查集
ans = []
for x, y in queries:
ans.append(weight_union_find_set.x_div_y(x, y))
return ans
https://leetcode-cn.com/problems/queue-reconstruction-by-height/
class Solution:
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
print('init people', people)
# 将height降序排序,将num进行升序排序
people.sort(key = lambda x:(-x[0], x[1]))
print('sorted people', people)
output = []
for p in people:
output.insert(p[1], p)
return output
https://leetcode-cn.com/problems/subarray-sum-equals-k/
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
'''
暴力:计算所有子数组的和,判断是否为k(超时),时间复杂度为n^3
'''
if not nums: return 0
L = len(nums)
res = 0
for i in range(L):
for j in range(i+1, L+1):
ij_sum = sum(nums[i:j])
if ij_sum == k:
res += 1
return res
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
'''
动规,dp[j]表示nums[i]到nums[j]的和
dp[j] = dp[j-1] + nums[j]
时间复杂度为n^2,依然超时
'''
if not nums: return 0
L = len(nums)
res = 0
dp = [0] * L
for i in range(L):
for j in range(i, L):
if i == j:
dp[j] = nums[j]
if dp[j] == k:
res += 1
continue
dp[j] = dp[j-1] + nums[j]
if dp[j] == k:
res += 1
return res
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
'''
利用hashmap将时间复杂度降低到N
'''
if not nums: return 0
L = len(nums)
res = 0
dp = {}
sums = 0
count = 0
for i in range(L):
sums += nums[i]
if sums == k:
count += 1
if sums -k in dp:
count += dp[sums-k]
dp[sums] = dp.get(sums, 0) + 1
return count
https://leetcode-cn.com/problems/task-scheduler/
class Solution:
def leastInterval(self, tasks: List[str], n: int) -> int:
task_num = [0] * 26
for c in tasks:
task_num[ord(c)-ord('A')] += 1
task_num.sort()
times = 0
while task_num[25] > 0:
i = 0
while i <= n:
if task_num[25] <= 0:
break
if i<26 and task_num[25-i] > 0:
task_num[25-i] -= 1
times += 1
i += 1
task_num.sort()
return times
https://leetcode-cn.com/problems/palindromic-substrings/
class Solution:
def countSubstrings(self, s: str) -> int:
'''
暴力找到所有的字串,然后判断是否回文
'''
if not s: return
res = 0
for i in range(len(s)):
for j in range(i+1, len(s)+1):
if s[i:j] == s[i:j][::-1]:
res += 1
return res
class Solution:
def countSubstrings(self, s: str) -> int:
'''
动态规划,dp[i][j]表示从i到j是否是回文串
dp[i][j] = dp[i+1][j-1] and s[i] == s[j]
边界条件: dp[i][i] = True
dp[i][i+1] = s[i]==s[i+1]
由于dp[i][j]依赖于dp[i+1][j-1],因此对于第一维数据要从下往上开始填入
'''
if not s: return
res = 0
# 上三角矩阵
dp = [[False] * len(s) for _ in range(len(s))]
# 边界条件
for i in range(len(s)):
dp[i][i] = True
res += 1
if i < len(s)-1:
dp[i][i+1] = (s[i] == s[i+1])
if dp[i][i+1]: res += 1
for i in range(len(s)-2, -1, -1):
for j in range(i+2, len(s)):
dp[i][j] = dp[i+1][j-1] and (s[i]== s[j])
if dp[i][j]: res+= 1
return res
github地址
更多文章请点击查看