每日一题——恢复二叉搜索树

菜鸡每日一题系列打卡99

每天一道算法题目 

小伙伴们一起留言打卡

坚持就是胜利,我们一起努力!

题目描述(引自LeetCode)

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

示例 1:


输入: [1,3,null,null,2]
   1
  /
 3
  \
   2


输出: [3,1,null,null,2]
   3
  /
 1
  \
   2
示例 2:


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


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

进阶:

  • 使用 O(n) 空间复杂度的解法很容易实现。

  • 你能想出一个只使用常数空间的解决方案吗?

题目分析

这是每日一题——验证二叉搜索树的进阶版,与该题目的思路类似,我们可以采用递归或者迭代的方式进行求解。

在每日一题——验证二叉搜索树我们说过,二叉搜索树的中序遍历是一个升序序列,因此,我们只需要在递归或者迭代中序遍历的过程中,发现并记录两处逆序的结点,然后将其交换即可。

为了给大家提供不同的思路,菜鸡在本文中将采用上述两种方式进行解答。话不多说,上代码!

代码实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
// 迭代中序遍历
class Solution {


    public void recoverTree(TreeNode root) {
        TreeNode first = null, second = null, flag = null;
        Stack stack = new Stack<>();


        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            if (flag != null && root.val < flag.val) {
                second = root;
                // 第一次遇到逆序
                if (first == null) first = flag;
                // 第二次遇到逆序
                else break;
            }
            flag = root;
            root = root.right;
        }


        int tmp = first.val;
        first.val = second.val;
        second.val = tmp;
    }


}

// 递归中序遍历
class Solution {


    private TreeNode first = null, second = null, flag = null;


    public void recoverTree(TreeNode root) {
        findNode(root);
        int tmp = first.val;
        first.val = second.val;
        second.val = tmp;
    }


    private void findNode(TreeNode root) {
        if (root == null) return;
        findNode(root.left);
        if (flag != null && root.val < flag.val) {
            second = root;
            //第一次遇到逆序
            if (first == null) first = flag;
            //第二次遇到逆序
            else return;
        }
        flag = root;
        findNode(root.right);
    }


}

代码分析

对代码进行分析,设二叉树的结点个数为n,高度为h,则:

  • 迭代中序遍历:最坏情况下,时间复杂度为O(n),空间复杂度为O(h)。

  • 递归中序遍历:最坏情况下,时间复杂度为O(n),空间复杂度为O(h)。

执行结果

每日一题——恢复二叉搜索树_第1张图片

迭代中序遍历的执行结果

每日一题——恢复二叉搜索树_第2张图片

递归中序遍历的执行结果

学习 | 工作 | 分享

????长按关注“有理想的菜鸡

只有你想不到,没有你学不到

你可能感兴趣的:(算法)