LeetCode(99):恢复二叉搜索树

Hard!

题目描述:

二叉搜索树中的两个节点被错误地交换。

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

示例 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) 空间复杂度的解法很容易实现。
  • 你能想出一个只使用常数空间的解决方案吗?

解题思路:

这道题要求我们复原一个二叉搜索树,说是其中有两个的顺序被调换了,题目要求上说O(n)的解法很直观,这种解法需要用到递归,用中序遍历树,并将所有节点存到一个一维向量中,把所有节点值存到另一个一维向量中,然后对存节点值的一维向量排序,再将排好的数组按顺序赋给节点。这种最一般的解法可针对任意个数目的节点错乱的情况。

C++解法一:

 1 // O(n) space complexity
 2 class Solution {
 3 public:
 4     void recoverTree(TreeNode *root) {
 5         vector<TreeNode*> list;
 6         vector<int> vals;
 7         inorder(root, list, vals);
 8         sort(vals.begin(), vals.end());
 9         for (int i = 0; i < list.size(); ++i) {
10             list[i]->val = vals[i];
11         }
12     }
13     void inorder(TreeNode *root, vector<TreeNode*> &list, vector<int> &vals) {
14         if (!root) return;
15         inorder(root->left, list, vals);
16         list.push_back(root);
17         vals.push_back(root->val);
18         inorder(root->right, list, vals);
19     }
20 };

然后我上网搜了许多其他解法,看到另一种是用双指针来代替一维向量的,但是这种方法用到了递归,也不是O(1)空间复杂度的解法,这里需要三个指针,first,second分别表示第一个和第二个错乱位置的节点,pre指向当前节点的中序遍历的前一个节点。这里用传统的中序遍历递归来做,不过再应该输出节点值的地方,换成了判断pre和当前节点值的大小,如果pre的大,若first为空,则将first指向pre指的节点,把second指向当前节点。这样中序遍历完整个树,若first和second都存在,则交换它们的节点值即可。这个算法的空间复杂度仍为O(n),n为树的高度。

C++解法二:

 1 // Still O(n) space complexity
 2 class Solution {
 3 public:
 4     TreeNode *pre;
 5     TreeNode *first;
 6     TreeNode *second;
 7     void recoverTree(TreeNode *root) {
 8         pre = NULL;
 9         first = NULL;
10         second = NULL;
11         inorder(root);
12         if (first && second) swap(first->val, second->val);
13     }
14     void inorder(TreeNode *root) {
15         if (!root) return;
16         inorder(root->left);
17         if (!pre) pre = root;
18         else {
19             if (pre->val > root->val) {
20                 if (!first) first = pre;
21                 second = root;
22             }
23             pre = root;
24         }
25         inorder(root->right);
26     }
27 };

道题的真正符合要求的解法应该用的Morris遍历,这是一种非递归且不使用栈,空间复杂度为O(1)的遍历方法,可参见我之前的博客Binary Tree Inorder Traversal 二叉树的中序遍历,在其基础上做些修改,加入first, second和parent指针,来比较当前节点值和中序遍历的前一节点值的大小,跟上面递归算法的思路相似。

C++解法三:

 1 // Now O(1) space complexity
 2 class Solution {
 3 public:
 4     void recoverTree(TreeNode *root) {
 5         TreeNode *first = NULL, *second = NULL, *parent = NULL;
 6         TreeNode *cur, *pre;
 7         cur = root;
 8         while (cur) {
 9             if (!cur->left) {
10                 if (parent && parent->val > cur->val) {
11                     if (!first) first = parent;
12                     second = cur;
13                 }
14                 parent = cur;
15                 cur = cur->right;
16             } else {
17                 pre = cur->left;
18                 while (pre->right && pre->right != cur) pre = pre->right;
19                 if (!pre->right) {
20                     pre->right = cur;
21                     cur = cur->left;
22                 } else {
23                     pre->right = NULL;
24                     if (parent->val > cur->val) {
25                         if (!first) first = parent;
26                         second = cur;
27                     }
28                     parent = cur;
29                     cur = cur->right;
30                 }
31             }
32         }
33         if (first && second) swap(first->val, second->val);
34     }
35 };

原文地址:https://www.cnblogs.com/ariel-dreamland/p/9159781.html

时间: 2024-10-12 00:59:15

LeetCode(99):恢复二叉搜索树的相关文章

Leetcode 99.恢复二叉搜索树

恢复二叉搜索树 二叉搜索树中的两个节点被错误地交换. 请在不改变其结构的情况下,恢复这棵树. 示例 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) 空间复杂度的解法很容易实现. 你能想出一个只使用常数空间的解决方案吗? 中序遍

LeetCode:验证二叉搜索树【98】

LeetCode:验证二叉搜索树[98] 题目描述 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身必须也是二叉搜索树. 示例 1: 输入: 2 / 1 3 输出: true 示例 2: 输入: 5 / 1 4   /   3 6 输出: false 解释: 输入为: [5,1,4,null,null,3,6].   根节点的值为 5 ,但是其右子节点值为 4

LeetCode 669. 修剪二叉搜索树(Trim a Binary Search Tree)

669. 修剪二叉搜索树 669. Trim a Binary Search Tree 题目描述 LeetCode LeetCode669. Trim a Binary Search Tree简单 Java 实现 TreeNode Class public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } class Solution { public TreeNode

Leetcode 450.删除二叉搜索树的节点

删除二叉搜索树的节点 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变.返回二叉搜索树(有可能被更新)的根节点的引用. 一般来说,删除节点可分为两个步骤: 首先找到需要删除的节点: 如果找到了,删除它. 说明: 要求算法时间复杂度为 O(h),h 为树的高度. 示例: root = [5,3,6,2,4,null,7] key = 3 给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它. 一个正确的答案

[LeetCode] 98. 验证二叉搜索树

题目链接 : https://leetcode-cn.com/problems/validate-binary-search-tree/ 题目描述: 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身必须也是二叉搜索树. 示例: 示例 1: 输入: 2 / 1 3 输出: true 示例 2: 输入: 5 / 1 4 / 3 6 输出: false 解释: 输入为

[Swift]LeetCode99. 恢复二叉搜索树 | Recover Binary Search Tree

Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing its structure. Example 1: Input: [1,3,null,null,2]   1   /  3     2 Output: [3,1,null,null,2]   3   /  1     2 Example 2: Input: [3,1,4,null,null,2]

LeetCode OJ:Recover Binary Search Tree(恢复二叉搜索树)

Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing its structure. 首先是O(N)空间的方法,用递归: 1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *ri

leetcode 538. 把二叉搜索树转换为累加树

题目 C++代码 /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* convertBST(TreeNode* root) { if(ro

二叉树-二叉搜索树(中序)

题型: (1)验证 (2)修复(排列不正确,修复) (3)构造(给排列求树-平衡的:种类) (4)利用性质求第n个结点 二叉搜索树的思路:中序输出+相关操作 如果要求空间复杂度O(1),考虑莫里斯遍历 98. 验证二叉搜索树    面试题 04.05. 合法二叉搜索树 (1) 思路:中序排列,看次序 1 class Solution { 2 public boolean isValidBST(TreeNode root) { 3 // if(root==null){ // 题目空树是true 4