Lever's Castle

99. 恢复二叉搜索树

November 21, 2018

https://leetcode-cn.com/problems/recover-binary-search-tree/

使用语言: Golang

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func recoverTree(root *TreeNode)  {
    var lastNode *TreeNode
    var inorder func(*TreeNode)
    var bigger *TreeNode
    var smaller *TreeNode
    inorder = func (_root *TreeNode) {
        if _root == nil {
            return
        }
        inorder(_root.Left)
        if bigger == nil && lastNode != nil && _root.Val < lastNode.Val {
            bigger = lastNode
        }
        if lastNode != nil && _root.Val < lastNode.Val  {
            smaller = _root
        }
        lastNode = _root
        inorder(_root.Right)
    }
    inorder(root)
    bigger.Val, smaller.Val = smaller.Val, bigger.Val
}

解题思路

首先,你要了解遍历一棵树有哪些方式:https://zh.wikipedia.org/wiki/%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86

前序遍历

图片

深度优先遍历 - 前序遍历: F, B, A, D, C, E, G, I, H.

中序遍历

图片 深度优先遍历 - 中序遍历: A, B, C, D, E, F, G, H, I.

后序遍历

图片 深度优先搜索 - 后序遍历: A, C, E, D, B, H, I, G, F.

广度优先遍历

图片 广度优先遍历 - 层次遍历: F, B, G, A, D, I, C, E, H.


其次你要明白什么是二叉搜索树

二叉搜索树的特性

  1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
  2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
  3. 任意节点的左、右子树也分别为二叉查找树;
  4. 没有键值相等的节点。

结合以上知识点,我们可以得出,按照 左 -> 中 -> 右 的顺序遍历(中序遍历)整棵树,我们能够拿到一个从小到大排列的数组。

那我们要做的事情就简单了: 中序遍历整棵树,记录上个节点的值,与当前节点的值做比较,找到不符合上个节点的值小于当前节点这一条件的节点,就是上面代码中的 bigger

又因为题中承诺只有两个节点被错误的交换了,也就是说,大的数放在了靠前的位置,小的数放在了靠后的位置,即第一个遇到的不满足条件的节点,就是 bigger,最后一次不满足条件的节点,就是 smaller

找到 bigger 和 smaller 之后,我们做一次简单的交换,就可以恢复整棵树了。


Lever

痕迹
没有过去,就没法认定现在的自己