94. 二叉树的中序遍历
- 给定一个二叉树,返回它的中序 遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [1,3,2]
思路1:迭代
递归的调用过程是不断往左边走,当左边走不下去了,就打印节点,并转向右边,然后右边继续这个过程。
我们在迭代实现时,就可以用栈来模拟上面的调用过程。
代码实现1:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
ret = []
stack = []
if not root:
return ret
while stack or root:
# 不断往左子树方向走,每走一次就将当前节点保存到栈中
# 这是模拟递归的调用
if root:
stack.append(root)
root = root.left
# 当前节点为空,说明左边走到头了,从栈中弹出节点并保存
# 然后转向右边节点,继续上面整个过程
else:
temp = stack.pop()
ret.append(temp.val)
root = temp.right
return ret
思路2:莫里斯遍历
用递归和迭代的方式都使用了辅助的空间,而莫里斯遍历的优点是没有使用任何辅助空间。
缺点是改变了整个树的结构,强行把一棵二叉树改成一段链表结构。
我们将黄色区域部分挂到节点5的右子树上,接着再把2和5这两个节点挂到4节点的右边。
这样整棵树基本上就变改成了一个链表了,之后再不断往右遍历。
代码实现2:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
ret = []
pre = None
while root:
# 如果左节点不为空,就将当前节点连带右子树全部挂到左节点的最右子树下面
if root.left: # 如果当前节点的左节点不为空
pre = root.left # 定义一个指针指向当前节点的左节点
while pre.right: # 找到左节点的最右子树
pre = pre.right
pre.right = root # 将当前节点连带其右子树一起挂到左节点的最右子树下
temp = root # 定义一个指针保存当前节点
root = root.left # 将当前节点指向其左节点
temp.left = None # 将保存的节点左侧置空
else: # 如果当前节点没有左节点,就将当前节点的值放入结果列表中,并将当前节点指向其右孩子
ret.append(root.val)
root = root.right
return ret
114. 二叉树展开为链表
- 给定一个二叉树,原地将它展开为链表。
示例:
给定二叉树
1
/ \
2 5
/ \ \
3 4 6
将其展开为:
1
\
2
\
3
\
4
\
5
\
6
思路1:非递归
代码实现1:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def flatten(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
pre = None
while root:
# 如果左子树不为空
if root.left:
# 定义一个指针,暂存右子树
temp = root.right
# 将根节点的右子树指向左子树,左子树置空
root.right = root.left
root.left = None
# 将根节点指向右子树
root = root.right
# 定义一个指针,找到原根节点原左子树的最右子树
pre = root
while pre.right:
pre = pre.right
# 将暂存的右子树挂到原根节点原左子树的最右子树上
pre.right = temp
# 若左子树为空,当前节点指向其右子树
else:
root = root.right
其他解法见:https://leetcode-cn.com/problems/flatten-binary-tree-to-linked-list/solution/dong-hua-yan-shi-si-chong-jie-fa-114-er-cha-shu-zh/
538/1038. 把二叉搜索树转换为累加树
思路1:递归
中序遍历 右-根-左
遍历完右边时,将当前值加到累加和ans中,并将根节点的值修改为累加和的值
代码实现1:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def __init__(self):
self.ans = 0
def convertBST(self, root: TreeNode) -> TreeNode:
if root is None:
return
self.convertBST(root.right)
self.ans += root.val
root.val = self.ans
self.convertBST(root.left)
return root
思路2:迭代
使用栈,把当前节点的右子树到最右子树压栈。
从栈中弹出元素,将当前值加到累加和中,并改变当前值为累加和的值。
若有左子树的将左子树及其右子树到最右子树压栈,重复以上过程。
代码实现2:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def convertBST(self, root: TreeNode) -> TreeNode:
stack = []
total = 0
node = root # 定义一个指针指向根节点,不能直接使用根节点
while stack or node:
# 如果一直有右节点,则将所有右节点压栈
if node:
stack.append(node)
node = node.right
else:
# 走到最右子树,从栈顶弹出当前子树最右下角元素
node = stack.pop()
total += node.val
node.val = total
# 当前节点的右子树已处理完,处理左子树
node = node.left
# 返回根节点
return root
98. 验证二叉搜索树
- 给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
示例:
示例 1:
输入:
2
/ \
1 3
输出: true
示例 2:
输入:
5
/ \
1 4
/ \
3 6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
根节点的值为 5 ,但是其右子节点值为 4 。
思路1:右下角向左上迭代
与 538 把二叉搜索树转换为累加树 相似,二叉搜索树也是从最右子树(即右下角)向左上是有顺序的。
对于 右子树 -> 结点 -> 左子树 ,每个元素都应该比下一个元素大。
为保证最右下角的元素有相应元素与其比较,我们使用 float(‘inf’) 代表无穷大。
float(‘inf’):无穷大;float(’-inf’):无穷小
代码实现1:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
if not root:
return True
stack = []
inorder = float('inf')
while stack or root:
if root:
stack.append(root)
root = root.right
else:
root = stack.pop()
if root.val >= inorder:
return False
inorder = root.val
root = root.left
return True