首页 > 其他分享 >力扣 99. 恢复二叉搜索树 [Morris]

力扣 99. 恢复二叉搜索树 [Morris]

时间:2022-12-05 17:55:49浏览次数:59  
标签:力扣 right TreeNode val 99 Morris root 节点 left

99. 恢复二叉搜索树

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

示例 1:

输入:root = [1,3,null,null,2]
输出:[3,1,null,null,2]
解释:3 不能是 1 的左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。

示例 2:

输入:root = [3,1,4,null,null,2]
输出:[2,1,4,null,null,3]
解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。

提示:

  • 树上节点的数目在范围 [2, 1000] 内
  • -231 <= Node.val <= 231 - 1

进阶:使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用 O(1) 空间的解决方案吗?

题解

O(1)可以通过Morris遍历实现。前一个题力扣 98. 验证二叉搜索树 [递归;迭代;Morris]可以帮助理解这个题。

未被错误交换前,通过中序遍历得到的数组,是升序的,如1,2,3,4,5,如果25交换,中序遍历会得到1,5,3,4,2。在遍历时,会发现两个不满足有效二叉树的情况:5,34,2。第一次不满足情况是5,3,当遍历到当前节点3时,前一个节点5>3,第二次是遍历到当前节点2时,前一个节点4>2,则第一次不满足的情况出现时,我们需要记录前一个节点5,当第二次情况出现时,记录当前节点2,遍历完之后交换记录的5和2,即可。

查看代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void recoverTree(TreeNode* root) {
        TreeNode* node=nullptr;//中序遍历条件下:当前节点的前一个节点
        TreeNode* error1=nullptr;//第一个错误的节点
        TreeNode* error2=nullptr;//第二个
        while (root != NULL)
        {
            if (root->left == NULL)
            {
                // cout << root->val << " ";//输出当前节点
                if(node&&node->val>root->val)//前一个节点存在,且不满足升序,需要记录错误节点
                {
                    if(!error1)//第一次
                        error1=node;
                    error2=root;//第二次
                }

                node=root;
                root = root->right;
            }
            else
            {
                // 找当前节点的前趋结点
                TreeNode* predecessor = root->left;
                while (predecessor->right != NULL
                    && predecessor->right != root)
                {
                    predecessor = predecessor->right;
                }

                // 使当前节点成为inorder的前序节点的右侧子节点
                if (predecessor->right == NULL)
                {
                    predecessor->right = root;
                    root = root->left;
                }
                //复原之前的修改
                else
                {
                    predecessor->right = NULL;
                    // cout << root->val << " ";//输出当前节点
                    if(node&&node->val>root->val)//前一个节点存在,且不满足升序
                    {
                        if(!error1)
                            error1=node;
                        error2=root;
                    }
                    node=root;
                    root = root->right;
                }
            }
        }
        if(error1){//进行交换
            int t=error1->val;
            error1->val=error2->val;
            error2->val=t;
        }
    }
};

 

标签:力扣,right,TreeNode,val,99,Morris,root,节点,left
From: https://www.cnblogs.com/fudanxi/p/16953005.html

相关文章

  • 力扣1337(java&python)-矩阵中战斗力最弱的 K 行(简单)
    题目:给你一个大小为 m *n 的矩阵 mat,矩阵由若干军人和平民组成,分别用1和0表示。请你返回矩阵中战斗力最弱的 k 行的索引,按从最弱到最强排序。如果第 i 行......
  • 力扣刷题02
    977.有序数组的平方给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。示例1:输入:nums=[-4,-1,0,3,10]输出:[0......
  • 力扣 98. 验证二叉搜索树
    98.验证二叉搜索树给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。有效 二叉搜索树定义如下:节点的左子树只包含 小于 当前节点的数。节......
  • 力扣 leetcode 209. 长度最小的子数组
    问题描述给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其和≥target的长度最小的连续子数组[numsl,numsl+1,...,numsr-1,numsr],并返......
  • 力扣18 四数之和
    题目:给你一个由n个整数组成的数组 nums,和一个目标值target。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a],nums[b],nums[c],nums[d]] (若两个四......
  • 力扣 leetcode 547. 省份数量
    问题描述有n个城市,其中一些彼此相连,另一些没有相连。如果城市a与城市b直接相连,且城市b与城市c直接相连,那么城市a与城市c间接相连。省份是一组直接或间接......
  • 力扣 leetcode 200. 岛屿数量
    问题描述给你一个由'1'(陆地)和'0'(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此......
  • 力扣刷题01
    704.二分查找给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。示例1:输入:num......
  • 力扣 leetcode 438. 找到字符串中所有字母异位词
    问题描述给定两个字符串s和p,找到s中所有p的异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。异位词指由相同字母重排列形成的字符串(包括相同的字......
  • 力扣 leetcode 11. 盛最多水的容器
    问题描述给定一个长度为n的整数数组height。有n条垂线,第i条线的两个端点是(i,0)和(i,height[i])。找出其中的两条线,使得它们与x轴共同构成的容器可以容......