树 94. 二叉树的中序遍历 114. 二叉树展开为链表 538/1038. 把二叉搜索树转换为累加树 98. 验证二叉搜索树

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
发布了51 篇原创文章 · 获赞 4 · 访问量 3512

猜你喜欢

转载自blog.csdn.net/yhhuang17/article/details/105234180