算法:恢复二叉搜索树

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

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

示例 1:
在这里插入图片描述

示例 2:
在这里插入图片描述

 

//显示中序遍历
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
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盼盼编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值