# 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 classSolution: defpreorderTraversal(self, root: Optional[TreeNode]) -> List[int]: '''1.递归方法''' defpreorder(root): ifnot root: return # 根结点在最开始处理 res.append(root.val) preorder(root.left) preorder(root.right)
res =[] preorder(root) return res
classSolution: defpreorderTraversal(self, root: Optional[TreeNode]) -> List[int]: '''2.非递归方法之一''' cur = root s, res = [], [] while cur orlen(s)>0: # 先遍历根结点及其左子树上的每一个子树的根结点 while cur: res.append(cur.val) s.append(cur) cur = cur.left # 左子树部分遍历完之后就可以遍历右边的子树部分了 cur = s.pop() cur = cur.right return res
classSolution: defpreorderTraversal(self, root: Optional[TreeNode]) -> List[int]: '''2.非递归方法之二''' s, res = [], [] if root: s.append(root) whilelen(s) > 0: cur = s.pop() res.append(cur.val) # 注意这里是先将右子结点入栈,再将左子结点入栈 # 这样出栈的时候,就是左子结点先出栈,右子结点后出栈 if cur.right : s.append(cur.right) if cur.left: s.append(cur.left) return res
classSolution: definorderTraversal(self, root: Optional[TreeNode]) -> List[int]: '''2.非递归方法''' cur = root s, res = [], [] while cur orlen(s)>0: while cur: # 先将结点入栈而不是读取值 s.append(cur) cur = cur.left cur = s.pop() # 弹出的结点再读取值 res.append(cur.val) cur = cur.right
classSolution: defpreorderTraversal(self, root: Optional[TreeNode]) -> List[int]: '''2.非递归方法之一''' '''按照先序遍历,只不过是右结点先于左结点,构造成:中-右-左,最后逆序: 得到 左-右-中 的顺序''' cur = root s, res = [], [] while cur orlen(s)>0: while cur: res.append(cur.val) s.append(cur) # 这里就是先处理左右当中的右子结点 cur = cur.right cur = s.pop() # 后处理左结点 cur = cur.left # 此时res是 中-右-左 的顺序,再逆序即可 res.reverse() return res
classSolution: defpreorderTraversal(self, root: Optional[TreeNode]) -> List[int]: '''2.非递归方法之二''' '''按照先序遍历,只不过是右结点先于左结点,构造成:中-右-左,最后逆序: 得到 左-右-中 的顺序''' s, res = [], [] if root: s.append(root) whilelen(s) > 0: cur = s.pop() res.append(cur.val) # 注意这里是先将左子结点入栈,再将右子结点入栈 # 这样出栈的时候,就是右子结点先出栈,左子结点后出栈 if cur.left : s.append(cur.left) if cur.right: s.append(cur.right) res.reverse() return res
classSolution: defpreorderTraversal(self, root: Optional[TreeNode]) -> List[int]: '''2.非递归方法之三''' '''不采用逆序的手段,直接按照需要的顺序求结果''' pre, cur = None, root s, res = [], [] while cur orlen(s)>0: while cur: s.append(cur) cur = cur.left cur = s.pop() # 如果当前结点没有右子结点,或者其右子结点上一轮已经处理过 # 就说明应该处理当前结点 ifnot cur.right or cur.right == pre: res.append(cur.val) pre = cur cur = None # 如果不是,说明存在右子结点,且尚未处理过右子结点 # 就先将当前结点放回栈,先处理其右子结点 else: s.append(cur) cur = cur.right
# 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 classSolution: deflevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: ifnot root: return [] # q作为临时队列 q = [root] res = [] while q: layer = [] # N 实际是当前要遍历的层的结点个数 N = len(q) for i inrange(N): # 模拟队列的处理方法,即先进的先出, cur = q.pop(0) layer.append(cur.val) if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) res.append(layer) return res
classSolution: deflevelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]: ifnot root: return [] # q作为临时队列 q = [root] res = [] while q: layer = [] # N 实际是当前要遍历的层的结点个数 N = len(q) for i inrange(N): # 模拟队列的处理方法,即先进的先出, cur = q.pop(0) layer.append(cur.val) if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) res.append(layer) res.reverse() return res
classSolution: defzigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: ifnot root: return [] # q作为临时队列 q = [root] res = [] L = 0 while q: layer = [] # N 实际是当前要遍历的层的结点个数 N = len(q) for i inrange(N): # 模拟队列的处理方法,即先进的先出, cur = q.pop(0) layer.append(cur.val) if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) if L % 2 == 0: res.append(layer) else: res.append(layer[::-1]) # 处理完当前层之后,层索引加一 L += 1
classSolution: defmaxDepth(self, root: Optional[TreeNode]) -> int: ifnot root: return0 q = [root] h = 0 while q: n = len(q) h+=1# 思路很简单,每有一层,就给深度加上1 for i inrange(n): cur = q.pop(0) if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) return h
classSolution: defminDepth(self, root: Optional[TreeNode]) -> int: ifnot root: return0 q, h = [root], 0
while q : n = len(q) h+=1 for i inrange(n): cur = q.pop(0) # 知道终点条件就行,达到此条件,直接可以返回了,不用继续遍历下一层了 if (not cur.left) and (not cur.right): return h if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) return h
classSolution: defrightSideView(self, root: Optional[TreeNode]) -> List[int]: '''1.广度优先遍历''' ifnot root: return [] q=[root] res = [] whilelen(q) > 0: N = len(q) for i inrange(N): cur = q.pop(0) if i == N-1: res.append(cur.val) if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) return res
classSolution: defconnect(self, root: 'Optional[Node]') -> 'Optional[Node]': ifnot root: return root q = [root] cur = root while q: N =len(q) pre = None for i inrange(N): cur = q.pop(0) # 层内链接 if pre: pre.next = cur pre = cur
if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) return root
classSolution: defconnect(self, root: 'Node') -> 'Node': ifnot root: return root q = [root] cur = root while q: N =len(q) pre = None for i inrange(N): cur = q.pop(0) if pre: pre.next = cur pre = cur
if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) return root
# 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
# inorder 元素的序号先存起来 inorder_index = {} for i, num inenumerate(inorder): inorder_index[num] = i defbuildNode(L1, R1, L2, R2): # 递归终止条件 if L1>R1 or L2>R2: returnNone
思路:这里的路径并不一定是指的从根结点出发到叶子结点的路径,而是从一个结点到另一个结点的任意路径。 考察二叉树最小的结构,即1个父结点连着两个子结点的情况: father / \ left right 如果我们的路径要经过father结点,那么路径一共就只有以下几种情况: 1.这一部分作为更大路径的子路径: a. father; b. father-left; c. father-right 2.自己这一部分构成一个路径: left-father-right
而至于我们要不要经过 father 结点,那就是看上面这4种情况,能否产生更大的路径和,即:经过father点是否对更大的路径的总和有正向增益?
# 确定存在根结点之后,来判断 # 这里采用层次遍历的方法 res = [] q = [root[0]] while q: N = len(q) layer = [] for i inrange(N): cur_idx = q.pop(0) # 检查cur_idx是否已经存在了, # 即判断这里cur_idx作为上一层的子结点,是否还指向了上面的层 if cur_idx in res: returnFalse else: layer.append(cur_idx)
if leftChild[cur_idx] != -1: q.append(leftChild[cur_idx]) if rightChild[cur_idx] != -1: q.append(rightChild[cur_idx])
classSolution: defisValidBST(self, root: Optional[TreeNode]) -> bool: cur = root res, s = [], [] while cur orlen(s)>0: while cur: s.append(cur) cur = cur.left cur = s.pop() # 在原始的中序遍历读值之前,先判断当前值,是否比前一个值大 # 就多了这么个步骤 if res: if cur.val <= res[-1]: returnFalse res.append(cur.val) cur = cur.right returnTrue
classSolution: defisCompleteTree(self, root: Optional[TreeNode]) -> bool: ifnot root: returnTrue # 将根节点的序号初始化为0 q = [(root,0)] i = -1 while q: N = len(q) for k inrange(N): cur, index = q.pop(0) # 每遍历一个结点,就将其数组排列顺序 i 加上1 i += 1 # 比较两个序号是否相等 if i != index: returnFalse # 在队列入队时,同时搭上其在满二叉树中对应位置的序号 if cur.left: q.append((cur.left, 2*index+1)) if cur.right: q.append((cur.right, 2*index+2)) returnTrue
classSolution: defkthSmallest(self, root: Optional[TreeNode], k: int) -> int: '''1.最简单的思路:先求中序遍历''' ''' # 1.1 递归 def inorder(node): if not node: return inorder(node.left) res.append(node.val) inorder(node.right) res = [] inorder(root) return res[k-1] # 1.2 迭代 s, res = [], [] cur = root while cur or s: while cur: s.append(cur) cur = cur.left cur = s.pop() res.append(cur.val) cur = cur.right return res[k-1] '''
'''2.不用完成全部中序遍历,而在遍历的过程中计数''' ''' # 2.1 递归方案 def inorder(node): if not node: return inorder(node.left) res[0] +=1 if res[0] == res[1]: res.append(node.val) return inorder(node.right) # 用res[0]存放计数器, 用res[1]存放目标值k res=[0,k] inorder(root) return res[-1] ''' # 2.2 迭代方案 s, i = [],0 cur = root while cur or s: while cur: s.append(cur) cur = cur.left cur= s.pop() i+=1 if i == k: return cur.val cur = cur.right
# DFS(node.left) # res = [0, k] # DFS(root) # return res[-1] '''2.迭代方案''' s, i = [], 0 cur = root while cur or s: while cur: s.append(cur) cur = cur.right cur = s.pop() i += 1 if i == k: return cur.val cur = cur.left
classSolution: deflowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': ''' # 1.直接使用普通二叉树 最近公共祖先的code [236题] if not root or root == p or root == q: return root # left的返回值,要么是None(即p和q都不在左子树中),要么是 p 或者q 或其最近公共祖先 left = self.lowestCommonAncestor(root.left, p, q) # right的返回值,要么是None(即p和q都不在右子树中),要么是 p 或者q 或其最近公共祖先 right = self.lowestCommonAncestor(root.right, p, q) if not left: # 如果left是None,则p和q都不在左子树中,则p和q都在右子树中,答案就是right返回值 return right if not right: # 如果right是None,则p和q都不在右子树中,则p和q都在左子树中,答案就是left 返回值 return left # 如果上面两个return都没有返回,说明left和right都不为空 # 那么p和q分别位于 左、右子树中,最近公共祖先就应该是root return root '''
# 依据BST自身的特性来做 ifnot root or root == p or root == q: return root # 如果两个点的值, 都比当前结点的值小, 那就去当前结点的左子树中寻找 if p.val < root.val and q.val < root.val: return self.lowestCommonAncestor(root.left, p, q) # 如果两个点的值, 都比当前结点的值大, 那就去当前结点的右子树中寻找 elif p.val > root.val and q.val > root.val: return self.lowestCommonAncestor(root.right, p, q) # 如果当前结点的值在p和q的值的中间, 那说明当前结点就是最近公共祖先 else: return root
definsert_word(self, root, word, index): '''具体的如何插入每个单词''' cur = root for ch in word: ifnot ch in cur: # 对于路径上的每一层,要保存其出现在 words列表 中的index cur[ch] = {'index':[], } cur = cur[ch] cur['index'].append(index) cur[self.end] = True
deffind_index(self, root, substr): '''查找具有子串:substr 的单词的索引''' cur = root for ch in substr: ifnot ch in cur: return -1 cur = cur[ch] return cur['index']
definsert_list(self, words): for i inrange(len(words)): self.insert_word(self.trie_prefix, words[i], i) self.insert_word(self.trie_suff, words[i][::-1], i)