LeetCode99. 恢复二叉搜索树

LeetCode99. 恢复二叉搜索树

题目描述

 /**
     * 
     * 给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。
     * 请在不改变其结构的情况下,恢复这棵树。
     * <p>
     * 进阶:使用 O(n) 空间复杂度的解法很容易实现。
     * 你能想出一个只使用常数空间的解决方案吗?
     * 
     */

思路分析

  1. 先对二叉搜索树进行中序遍历,将每个节点的值存储到集合中
  2. 如果节点没有被交换,正常情况下,通过中序遍历后的二叉搜索树的节点值是升序排列的
  3. 当有节点发生交换时,得到的序列会出现逆序的情况,因此可以通过逆序判断哪两个节点被交换,将节点对应的值记录在数组中
  4. 再次遍历二叉搜索树,找到被交换的节点的值 ,并交换
  5. 源码及分析见下

源码及分析

public void recoverTree(TreeNode root) {
        //定义集合保存中序遍历的结果
        List<Integer> list = new ArrayList<>();
        inorder(root, list);
        int[] swapped = findTwoSwapped(list);
        recover(root, 2, swapped[0], swapped[1]);
    }

    /**
     * 使用中序遍历将二叉树各个节点的值保存在集合中
     *
     * @param root 根节点
     * @param list 保存二叉树节点的值
     */
    public void inorder(TreeNode root, List<Integer> list) {
        if (root == null) {
            return;
        }
        //向左递归
        inorder(root.left, list);
        list.add(root.val);
        //向右递归
        inorder(root.right, list);
    }

    /**
     * @param list 二叉树的元素
     * @return 返回找到的数字
     */
    public int[] findTwoSwapped(List<Integer> list) {
        //定义变量记录要交换的值
        int x = -1, y = -1;
        //遍历集合寻找逆序的树
        for (int i = 0; i < list.size() - 1; i++) {
            //如果发现有逆序的数,则记录
            if (list.get(i) > list.get(i + 1)) {
                y = list.get(i + 1);
                if (x == -1) {
                    x = list.get(i);
                } else {
                    break;
                }
            }
        }
        return new int[]{x, y};
    }

    /**
     * 通过递归将x和y的值所在节点交换
     *
     * @param root  根节点
     * @param count 要交换的数字个数
     * @param x     要交换的值1
     * @param y     要交换的值2
     */
    public void recover(TreeNode root, int count, int x, int y) {
        if (root != null) {
            //递归时如果发现当前节点的值是x 或者y
            if (root.val == x || root.val == y) {
                root.val = root.val == x ? y : x;
                //递归结束条件,即交换两次后结束
                if (--count == 0) {
                    return;
                }
            }
            //向右递归查找并交换
            recover(root.right, count, x, y);
            //向左递归查找并交换
            recover(root.left, count, x, y);
        }
    }

posted @ 2021-06-22 09:09  mx_info  阅读(39)  评论(0)    收藏  举报