99. 恢复二叉搜索树

恢复二叉搜索树

二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
示例 2:

输入: [3,1,4,null,null,2]

3
/
1 4
/
2

输出: [2,1,4,null,null,3]

2
/ \
1 4
/
3
进阶:

使用 O(n) 空间复杂度的解法很容易实现。
你能想出一个只使用常数空间的解决方案吗?

思路

在二叉搜索树中,给定节点的左子树中的节点要小于他,其右子树的节点要大于给定节点。二叉搜索树的中序遍历一定是单调递增的。
这道题的关键是找到那两个节点,然后进行交换
第一个节firstNode点,是第一个按照中序遍历时候前一个节点大于后一个节点,我们选取前一个节点,这里指节点4;
第二个节点secondNode,是在第一个节点找到之后, 后面出现前一个节点大于后一个节点,我们选择后一个节点,这里指节点1;
在这里插入图片描述
当两个节点相邻时,firstNode就是前一个数,secondNode就是后一个数。
解法一:
中序遍历时使用栈将树的节点保存起来

# @lc code=start
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def recoverTree(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        # 构建两个指针
        # 第一个节点,是第一个按照中序遍历时候前一个节点大于后一个节点,我们选取前一个节点
        # 第二个节点,是在第一个节点找到之后, 后面出现前一个节点大于后一个节点,我们选择后一个节点
        firstNode = None 
        secondNode = None
        pre = TreeNode(float("-inf"))
        stack = []
        p = root 
        while p or stack:
            while p:
                stack.append(p)
                p = p.left 

            p = stack.pop()
            # 当找到第一个节点之后,firstNode就不变了
            # 在第一个节点处,firstNode等于前一个节点的值,secondNode等于后一个节点的值
            # 所以在要交换的两个节点相邻时也满足条件
            # 
            if not firstNode and pre.val>p.val:
                firstNode = pre 

            # 第二个节点, 是在第一个节点找到之后, 后面出现前一个节点大于后一个节点,我们选择后一个节点
            if firstNode and pre.val>p.val:
                secondNode = p 

            pre = p 
            p = p.right 

        firstNode.val, secondNode.val = secondNode.val, firstNode.val 

解法二:
使用莫里斯遍历,让部分下层的空指针指向上层

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def recoverTree(self, root: TreeNode) -> None:
        firstNode = None 
        secondNode = None
        pre = TreeNode(float("-inf"))
        currrent = root 
        nxt = None 
        while currrent!=None:
            nxt = currrent.left 
            if nxt!=None:
                while nxt.right!=None and nxt.right!=currrent: # 寻找左子树的最右节点
                    nxt = nxt.right 
				# 如果最右节点的右节点是None,将其指向当前这部分子树的根节点
                if nxt.right==None: 
                    nxt.right = currrent 
                    currrent = currrent.left
                    continue 

                else:
                    nxt.right = None
			# 确定两个指针
            if not firstNode and pre.val>currrent.val:
                firstNode = pre 
            if firstNode and pre.val>currrent.val:
                secondNode = currrent
			# 直到到达最左边的节子点
            pre = currrent
            currrent = currrent.right  # 遍历右子树
        firstNode.val, secondNode.val = secondNode.val, firstNode.val

解法三:先中序遍历一次得到所有的值,再对其进行排序,然后再进行一次中序遍历将排序后的值赋给每个节点

# 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.val_list = []
        self.index = 0 
    def recoverTree(self, root: TreeNode) -> None:
        p = root
        self.inorder(p)# 先中序遍历一次
        self.val_list.sort() # 对遍历得到的值进行排序
        self.getorder(root) # 将排序后的值赋给每一个节点
        
    # 中序遍历一次,得到所有的值
    def inorder(self, root):
        if root!=None:
            self.inorder(root.left)
            self.val_list.append(root.val)
            self.inorder(root.right)
	# 再次中序遍历,给每个节点赋值
    def getorder(self, root):
        if root!=None:
            self.getorder(root.left)
            root.val = self.val_list[self.index]
            self.index += 1 
            self.getorder(root.right)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值