前后中遍历-非递归写法
中序遍历稍微难一些,第二种写法不太好想出来
94. 二叉树的中序遍历
def inorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return None
# 中序遍历写法1
stack,ans = [root,],[]
while(stack):
while(root.left):
stack.append(root.left)
root = root.left
node = stack.pop()
ans.append(node.val)
if node.right:
stack.append(node.right)
root = node.right
# 中序遍历写法2 -> 写法1的升级写法,不需要赋值临时节点
stack,ans = [],[]
while(stack or root):
while(root):
stack.append(root)
root = root.left
root = stack.pop()
ans.append(root.val)
root = root.right
return ans
中序遍历的应用
验证二叉搜索树,保底写法:遍历之后放到数组中,然后判断数组是否严格升序
98. 验证二叉搜索树
def isValidBST(self, root: TreeNode) -> bool:
if not root: return True
# 掌握中序法1写法
stack,inorder = [root,],float('-inf')
while(stack):
while(root.left):
stack.append(root.left)
root = root.left
node = stack.pop()
if node.val <= inorder: return False
inorder = node.val
if(node.right):
stack.append(node.right)
root = node.right
return True
# 掌握中序法2写法
stack, inorder = [], float('-inf')
while stack or root:
while root:
stack.append(root)
root = root.left
root = stack.pop()
if root.val <= inorder:
return False
inorder = root.val
root = root.right
return True
590. N叉树的后序遍历
class Solution:
def postorder(self, root: 'Node') -> List[int]:
if root is None:
return []
stack, res = [root, ], []
while(stack):
root = stack.pop()
if(root is not None):
res.append(root.val)
for child in root.children:
stack.append(child)
return res[::-1]
BFS&层次遍历
使用队列,把每个还没有搜索到的点依次放入队列,然后再弹出队列的头部元素当做当前遍历点。BFS总共有两个模板:
如果不需要确定当前遍历到了哪一层,BFS模板如下。
while queue 不空:
cur = queue.pop()
for 节点 in cur的所有相邻节点:
if 该节点有效且未访问过:
queue.push(该节点)
如果要确定当前遍历到了哪一层,BFS模板如下。
这里增加了level表示当前遍历到二叉树中的哪一层了,也可以理解为在一个图中,现在已经走了多少步了。size表示在当前遍历层有多少个元素,也就是队列中的元素数,我们把这些元素一次性遍历完,即把当前层的所有元素都向外走了一步。
level = 0
while queue 不空:
size = queue.size()
while (size --) {
cur = queue.pop()
for 节点 in cur的所有相邻节点:
if 该节点有效且未被访问过:
queue.push(该节点)
}
level ++;
BFS经典例题1 - 129. 求根到叶子节点数字之和
思路:维护两个队列,一个是正常用的存储节点的,一个是节点的值方便用来做计算
def sumNumbers(self, root: TreeNode) -> int:
if not root: return 0
from collections import deque
q1,q2 = deque([root]),deque([root.val])
res = 0
while(q1):
node = q1.popleft()
v = q2.popleft()
l,r = node.left, node.right
if l:
q1.append(l)
q2.append(v*10+l.val)
if r:
q1.append(r)
q2.append(v*10+r.val)
if not l and not r:
res+=v
return res
BFS经典例题2 - 116. 填充每个节点的下一个右侧节点指针
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:
return None
from collections import deque
q=deque([root])
while(q):
size = len(q)
for i in range(size):
node = q.popleft()
if i == size - 1:
node.next = None
else:
node.next = q[0] #deque支持通过下标取元素
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return root
BFS经典例题 3 -127. 单词接龙
def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
size = len(beginWord)
dic = defaultdict(list)
for word in wordList:
for i in range(size):
key = word[:i]+"*"+word[i+1:]
dic[key].append(word)
from collections import deque
q = deque()
q.append((beginWord,1))
visited = defaultdict(bool)
visited[beginWord] = True
while q:
current_word,level = q.popleft()
size = len(current_word)
for i in range(size):
key = current_word[:i]+'*'+current_word[i+1:]
for neighour in dic[key]:
if neighour == endWord:
return level+1
if not visited[neighour]:
visited[neighour] = True
q.append((neighour,level+1))
return 0
BFS经典例题4 - N叉树的层次遍历
def levelOrder(self, root: 'Node') -> List[List[int]]:
if not root: return root
d = collections.deque()
d.append(root)
res = []
while d :
n = len(d)
tmp = []
for i in range(n):
node = d.popleft()
tmp.append(node.val)
if node.children:
d.extend(node.children)
res.append(tmp)
return res
递归遍历
面试题 04.02. 最小高度树
自己的代码
def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
if(len(nums)==0):
return None
mid = len(nums) // 2
root = TreeNode()
root.val = nums[mid]
root.left = self.sortedArrayToBST(nums[0:mid])
root.right = self.sortedArrayToBST(nums[mid+1:len(nums)])
return root
下面是标准答案,可以看到一些细节上的差异
def sortedArrayToBST(self, nums: List[in]) -> TreeNode:
if not len(nums): return
mid = len(nums) // 2
root = TreeNode(nums[mid])
root.left = self.sortedArrayToBST(nums[: mid])
root.right = self.sortedArrayToBST(nums[mid + 1: ])
return root
其他一些树的问题
二叉树深度
def maxDepth(self, root: TreeNode) -> int:
if(root is None):
return 0
elif(root.left is None and root.right is None):
return 1
else :
return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
二叉树镜像-递归
def mirrorTree(self, root: TreeNode) -> TreeNode:
if(root is None):
return
else:
root.left, root.right = root.right, root.left
self.mirrorTree(root.left)
self.mirrorTree(root.right)
return root
二叉搜索树所有节点值的和-递归
def rangeSumBST(self, root: TreeNode, L: int, R: int) -> int:
if(root is None):
return 0
elif(root.val>=L and root.val<=R):
l,r = 0,0
if(root.left):
l = self.rangeSumBST(root.left,L,R)
if(root.right):
r = self.rangeSumBST(root.right,L,R)
return root.val + l + r
二叉树合并
def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode:
if(not t1 and not t2):
return None
elif(t1 and not t2):
return t1
elif(t2 and not t1):
return t2
else:
t = TreeNode()
t.val = t1.val + t2.val
t.left = self.mergeTrees(t1.left, t2.left)
t.right = self.mergeTrees(t1.right, t2.right)
return t
1.589. N叉树的前序遍历
def preorder(self, root: 'Node') -> List[int]:
res = []
def helper(root):
if not root:
return
res.append(root.val)
for child in root.children:
helper(child)
helper(root)
return res
2. 108. 将有序数组转换为二叉搜索树
这个树的也不会
def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
def helper(left, right):
if left > right:
return None
# 总是选择中间位置左边的数字作为根节点
mid = (left + right) // 2
root = TreeNode(nums[mid])
root.left = helper(left, mid - 1)
root.right = helper(mid + 1, right)
return root
return helper(0, len(nums) - 1)
下面的456分别是二叉树的三个遍历,重新复习一下吼吼吼
class Solution:
# 前序遍历 根左右 让右边的后弹出,所以右边的要先压栈
def preorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return None
stack,ans = [root],[]
while(stack):
tmp = stack.pop()
ans.append(tmp.val)
if tmp.right:
stack.append(tmp.right)
if tmp.left:
stack.append(tmp.left)
return ans
# 后序遍历 左右根 相当于根右左 然后取反就行 让左边的后弹出,所以左边的先压栈
def postorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return None
stack,ans = [root],[]
while(stack):
tmp = stack.pop()
ans.append(tmp.val)
if tmp.left:
stack.append(tmp.left)
if tmp.right:
stack.append(tmp.right)
return ans[::-1]
# 中序遍历 先把左节点全部入栈 弹出过程中查看是否有右节点
def inorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return None
stack, ans = [root,],[]
while(stack):
while root.left:
stack.append(root.left)
root = root.left
node = stack.pop()
ans.append(node.val)
if(node.right):
stack.append(node.right)
root = node.right
return ans
1. 199. 二叉树的右视图
def rightSideView(self, root: TreeNode) -> List[int]:
dic = {}
max_depth = -1
stack = [(root,0)]
while(stack):
#每次先弹出的是右边节点的值
#没有右边节点就会弹出左边的,都没有表示没有节点了
node, depth = stack.pop()
if (node):
max_depth = max(max_depth,depth)
dic[depth] = dic.setdefault(depth,node.val)
# 下面这两行代码换一下就可以从右视图变成左视图
stack.append((node.left,depth+1))
stack.append((node.right,depth+1))
return list(dic.values())