[Leetcode] Recover Binary Search Tree

Recover Binary Search Tree 题解

题目来源:https://leetcode.com/problems/recover-binary-search-tree/description/


Description

Two elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.

Note:

A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?

Solution

解法一:使用递归中序遍历找到乱序节点位置

class Solution {
private:
    TreeNode *first = nullptr;
    TreeNode *second = nullptr;
    TreeNode *pre = nullptr;
    void traverse(TreeNode *node) {
        if (node) {
            traverse(node -> left);

            if (!first && pre -> val >= node -> val)  // first还没有找到,出现乱序
                first = pre;
            if (first && pre -> val >= node -> val)  // first已经找到,出现乱序
                second = node;

            pre = node;

            traverse(node -> right);
        }
    }
public:
    void recoverTree(TreeNode* root) {
        TreeNode temp(INT_MIN);
        pre = &temp;

        traverse(root);

        swap(first -> val, second -> val);
    }
};

解法二:使用Morris中序遍历找到乱序节点位置

class Solution {
public:
    void recoverTree(TreeNode* root) {
        TreeNode *first = NULL;
        TreeNode *second = NULL;
        TreeNode *pre = NULL;
        TreeNode *temp = NULL;
        // Morris遍历
        while (root) {
            if (root -> left) {
                temp = root -> left;
                while (temp -> right && temp -> right != root) {
                    // 找到左子树的最右节点
                    temp = temp -> right;
                }
                if (temp -> right) { // 左子树的最右节点已经连接到pre的左侧
                    if (pre && pre -> val >= root -> val) {
                        if (!first) {
                            first = pre;
                            // 因为可能只存在一个乱序位置,所以要先设置second
                            second = root;
                        } else {
                            second = root;
                        }
                    }
                    // 左子树已经遍历
                    pre = root; // 右子树之前访问的点即为root
                    temp -> right = NULL; // 断开左子树最右侧节点与root的连接
                    root = root -> right; // 切换到右子树进行遍历
                } else { // 仍未连接到pre,则进行连接
                    temp -> right = root; // 将左子树最右侧节点与root连接
                    root = root -> left; // 左子树还没遍历,切换到左子树进行遍历
                }
            } else {
                // 左子树为空的情况
                if (pre && pre -> val >= root -> val) {
                    if (!first) {
                        first = pre;
                        second = root;
                    } else {
                        second = root;
                    }
                }
                // 左子树为空,切换到右子树
                pre = root; // 右子树之前访问的点即为root
                root = root -> right; // 切换到右子树进行遍历
            }
        }
        if (first && second)
            swap(first -> val, second -> val);
    }
};

解题描述

这道题题意是,给出一棵二叉搜索树,树上有两个节点被交换了位置,要求恢复这棵二叉搜索树。上面给出两种解法,分别是递归中序遍历解法和Morris中序遍历的解法。其中Morris中序遍历是一种非递归的树遍历方式,并且不需要借助队列或者栈等数据结构,具有常数空间复杂度。

原文地址:https://www.cnblogs.com/yanhewu/p/8456794.html