DFS-困难
1 124. 二叉树中的最大路径和 https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/
考点:
1、后续遍历,根据左右节点和当前节点的值,判断当前节点最大路径的值
2、一个需要注意点是,左右节点+当前节点作为步骤1之外一个单独的路径(红色字体部分代码)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def set_val(self, value):
if value > self.max_num:
self.max_num = value
def helper(self, root):
if root == None:
return None
left_max = self.helper(root.left)
right_max = self.helper(root.right)
# 叶子节点
if left_max == None and right_max == None:
self.set_val(root.val)
return root.val
elif left_max == None:
value = max(right_max + root.val, root.val)
self.set_val(value)
return value
elif right_max == None:
value = max(left_max + root.val, root.val)
self.set_val(value)
return value
else:
value = max(left_max + root.val, right_max + root.val, root.val)
value2 = left_max + right_max + root.val
if value > value2:
self.set_val(value)
else:
self.set_val(value2)
return value
def maxPathSum(self, root: TreeNode) -> int:
# 后序遍历, 则当前节点最大路径为 max(左右+当前节点, 左+当前节点,右+当前节点, 当前节点)
self.max_num = root.val
self.helper(root)
return self.max_num
2 980. 不同路径 III https://leetcode-cn.com/problems/unique-paths-iii/
考点:
1、深度搜索,碰到非-1值迭代搜索路径; 结束条件为 碰到结束点,满足条件是走过了全路径,即走过路径长度等于全路径长度
class Solution:
def helper(self, grid, cur, cur_path):
print(cur, self.end)
if cur == self.end:
if len(cur_path) == self.path_len:
self.result.append(cur_path)
return
tmp_i, tmp_j = cur
for i,j in [(tmp_i+1, tmp_j), (tmp_i -1, tmp_j), (tmp_i, tmp_j +1), (tmp_i, tmp_j -1)]:
if 0 <= i < self.row and 0 <= j < self.col and not grid[i][j] == -1 and (i, j) not in cur_path:
tmp_cur_path = list(cur_path)
tmp_cur_path.append((i, j))
self.helper(grid, (i, j), tmp_cur_path)
def uniquePathsIII(self, grid: List[List[int]]) -> int:
self.row = len(grid)
self.col = len(grid[0])
start = None
self.end = None
blocked = 0
for i in range(self.row):
for j in range(self.col):
if grid[i][j] == 1:
start = (i, j)
elif grid[i][j] == -1:
blocked += 1
elif grid[i][j] == 2:
self.end = (i, j)
self.path_len = self.row * self.col - blocked
# DFS
self.result = []
self.helper(grid, start, [start])
return len(self.result)
3. 839. 相似字符串组 https://leetcode-cn.com/problems/similar-string-groups/
考点: 深度搜索
class Solution:
def fulfil(self, str1, str_list):
str_len = len(str1)
for str2 in str_list:
diff = 0
for i in range(str_len):
if not str1[i] == str2[i]:
diff += 1
if diff == 2 or diff == 0:
return True
return False
def helper(self, A):
if len(A) == 0:
return
found = False
tmp_A = list(A)
for s_str in A:
for result in self.results:
if self.fulfil(s_str, result):
found = True
result.append(s_str)
tmp_A.remove(s_str)
if not found:
tmp_str = A[0]
self.results.append([tmp_str])
tmp_A.remove(tmp_str)
self.helper(tmp_A)
def numSimilarGroups(self, A: List[str]) -> int:
self.results = []
self.helper(A)
return len(self.results)
考虑优化,设置2级结果,已经遍历完全的组不参与遍历,继续超时
class Solution:
def fulfil(self, str1, str_list):
str_len = len(str1)
for str2 in str_list:
diff = 0
for i in range(str_len):
if not str1[i] == str2[i]:
diff += 1
if diff == 2 or diff == 0:
return True
return False
def helper(self, A):
if len(A) == 0:
self.results.append(self.results_tmp)
self.results_tmp = []
return
found = False
tmp_A = list(A)
for s_str in A:
if self.fulfil(s_str, self.results_tmp):
found = True
self.results_tmp.append(s_str)
tmp_A.remove(s_str)
if not found:
tmp_str = A[0]
if self.results_tmp:
self.results.append(self.results_tmp)
self.results_tmp = []
tmp_A.remove(tmp_str)
self.results_tmp.append(tmp_str)
self.helper(tmp_A)
def numSimilarGroups(self, A: List[str]) -> int:
self.results = []
self.results_tmp = []
self.helper(A)
return len(self.results)
想来想去,该种方法都需要 n *n 循环
j继续优化,把字符窜分成一个个小类计算,还是时间超时,只能跑31 / 63 个通过测试用例
class Solution:
def fulfil(self, str1, str_list):
str_len = len(str1)
for str2 in str_list:
diff = 0
for i in range(str_len):
if not str1[i] == str2[i]:
diff += 1
if diff == 2 or diff == 0:
return True
return False
def helper(self, A):
if len(A) == 0:
return
# 获取字符窜
tmp_str = A[0]
ori_list = [tmp_str]
# 获取相似字符窜,删除
A.remove(tmp_str)
while ori_list:
found = False
tmp_list = []
tmp_A = list(A)
for a in tmp_A:
if self.fulfil(a, ori_list):
found = True
tmp_list.append(a)
A.remove(a)
ori_list = list(tmp_list)
if not found:
break
# print(A)
self.results += 1
# 迭代
self.helper(A)
def numSimilarGroups(self, A: List[str]) -> int:
# 时间超时,性能优化问题,首先想到是dict, 所以问题就变成使用什么样的key
self.results = 0
A_dict = collections.defaultdict(set)
for a in A:
A_dict["".join(sorted(a))].add(a)
# print(A_dict)
for value in A_dict.values():
self.helper(list(value))
# self.helper(A)
return self.results
继续使用并查集优化,多通过一个用例,忧伤(32 / 63 个通过测试用例)
class Solution:
def search(self, a, ilist):
if ilist[a] != a:
ilist[a] = self.search(ilist[a], ilist)
return ilist[a]
def union(self, a, b, ilist):
aa = self.search(a, ilist)
bb = self.search(b, ilist)
# print("********")
# print(a, aa)
# print(b, bb)
# print("%%%%%%%%%")
if aa > bb:
ilist[aa] = bb
else:
ilist[bb] = aa
# print("****", ilist)
def match(self, a, b):
diff_len = 0
for i in range(len(a)):
if not a[i] == b[i]:
diff_len += 1
if diff_len == 2:
return True
return False
def helper(self, str_list):
if len(str_list) == 0:
return
len_A = len(str_list)
ilist = []
ilist_dict = dict()
for i in range(len_A):
ilist.append(i)
ilist_dict[str_list[i]] = i
# print(ilist)
# print(ilist_dict)
for i in range(len_A-1):
for j in range(i+1, len_A):
if self.match(str_list[i], str_list[j]):
# print("&", ilist)
# print(i, j)
self.union(i ,j, ilist)
# print(ilist)
for i in range(len(ilist)):
self.search(i, ilist)
self.results += len(set(ilist))
def numSimilarGroups(self, A: List[str]) -> int:
# 时间超时,性能优化问题,首先想到是dict, 所以问题就变成使用什么样的key
self.results = 0
A_dict = collections.defaultdict(set)
for a in A:
A_dict["".join(sorted(a))].add(a)
# print(A_dict)
for value in A_dict.values():
self.helper(list(value))
# self.helper(A)
return self.results
4 514. 自由之路 https://leetcode-cn.com/problems/freedom-trail/
考点:
1、使用常规的 顺时针,逆时针的深度搜索,会超时
class Solution:
def findRotateSteps(self, ring: str, key: str) -> int:
# 1至100之间,值不大,尝试使用深度搜索
ring_len = len(ring)
key_len = len(key)
result = set()
result.add(float('inf'))
def helper(ikey, cur_pos, cur_step):
if not ikey:
result.add(cur_step)
return
if cur_step > min(result):
return
if ring[cur_pos] == ikey[0]:
helper(ikey[1:], cur_pos, cur_step)
return
# 顺时针
for i in range(1, ring_len):
if ikey[0] == ring[(cur_pos + i) % ring_len]:
helper(ikey[1:], (cur_pos + i) % ring_len, cur_step + i)
break
# 逆时针
for i in range(1, ring_len):
if ikey[0] == ring[cur_pos - i]:
helper(ikey[1:], (cur_pos - i + ring_len) % ring_len, cur_step + i)
break
helper(key, 0, 0)
return min(result) + key_len
1、首先是一个最大值、最小值问题,然后根据前一个值,得到后一个值的最优解,可以使用动态规划
class Solution:
def findRotateSteps(self, ring: str, key: str) -> int:
ring_len = len(ring)
key_len = len(key)
grid = [[float('inf')] * ring_len for _ in range(key_len)]
# 各元素的位置
pos = collections.defaultdict(list)
for i in range(ring_len):
pos[ring[i]].append(i)
# print(pos)
def min_distance(x, y):
if x > y:
x, y = y, x
return min(y-x, ring_len-(y-x))
# 设置初始位置
for index in pos[key[0]]:
grid[0][index] = min_distance(0, index)
for i in range(1, len(key)):
for j in pos[key[i]]:
for k in pos[key[i-1]]:
# print(grid)
grid[i][j] = min(grid[i][j], min_distance(k, j) + grid[i-1][k])
return min(grid[-1]) + len(key)

浙公网安备 33010602011771号