1、题目描述
二叉搜索树中的两个节点被错误地交换。

请在不改变其结构的情况下,恢复这棵树。

示例 1:
算法:恢复二叉搜索树_算法

示例 2:
算法:恢复二叉搜索树_编程开发_02

 

//显示中序遍历
func recoverTree(root *TreeNode)  {
    nums := []int{}

    var inorder func(node *TreeNode)
    inorder = func(node *TreeNode) {
        if node == nil {
            return
        }
        inorder(node.Left)
        nums = append(nums, node.Val)
        inorder(node.Right)
    }

    inorder(root)
    x, y := findTwoSwapped(nums)
    fmt.Println(x, y)
    recover(root, 2, x, y)
}

//x取大数,y取小数
func findTwoSwapped(nums []int) (int, int) {
    x, y := -1, -1
    for i := 0; i < len(nums) - 1; i++ {
        if nums[i + 1] < nums[i] {
            y = nums[i+1]
            if x == -1 {
                x = nums[i]
            } else {
                break
            }
        }
    }
    return x, y
}

func recover(root *TreeNode, count, x, y int) {
    if root == nil {
        return
    }
    if root.Val == x || root.Val == y {
        if root.Val == x {
            root.Val = y
        } else {
            root.Val = x
        }
        //记录交换次数,要双方都赋值才算交换完成
        count--
        if count == 0 {
            return
        }
    }
    //递归
    recover(root.Right, count, x, y)
    recover(root.Left, count, x, y)
}

//隐式中序遍历
func recoverTree(root *TreeNode)  {
    stack := []*TreeNode{}
    var x, y, pred *TreeNode

    for len(stack) > 0 || root != nil {
        for root != nil {
            stack = append(stack, root)
            //一路向左
            root = root.Left
        }

        //通过出栈实现中序遍历
        root = stack[len(stack)-1]
        stack = stack[:len(stack)-1]

        if pred != nil && root.Val < pred.Val {
            y = root
            if x == nil {
                x = pred
            } else {
                break
            }
        }
        pred = root
        root = root.Right
    }

    x.Val, y.Val = y.Val, x.Val
}