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++解法一:

 // O(n) space complexity
class Solution {
public:
void recoverTree(TreeNode *root) {
vector<TreeNode*> list;
vector<int> vals;
inorder(root, list, vals);
sort(vals.begin(), vals.end());
for (int i = ; i < list.size(); ++i) {
list[i]->val = vals[i];
}
}
void inorder(TreeNode *root, vector<TreeNode*> &list, vector<int> &vals) {
if (!root) return;
inorder(root->left, list, vals);
list.push_back(root);
vals.push_back(root->val);
inorder(root->right, list, vals);
}
};

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

C++解法二:

 // Still O(n) space complexity
class Solution {
public:
TreeNode *pre;
TreeNode *first;
TreeNode *second;
void recoverTree(TreeNode *root) {
pre = NULL;
first = NULL;
second = NULL;
inorder(root);
if (first && second) swap(first->val, second->val);
}
void inorder(TreeNode *root) {
if (!root) return;
inorder(root->left);
if (!pre) pre = root;
else {
if (pre->val > root->val) {
if (!first) first = pre;
second = root;
}
pre = root;
}
inorder(root->right);
}
};

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

C++解法三:

 // Now O(1) space complexity
class Solution {
public:
void recoverTree(TreeNode *root) {
TreeNode *first = NULL, *second = NULL, *parent = NULL;
TreeNode *cur, *pre;
cur = root;
while (cur) {
if (!cur->left) {
if (parent && parent->val > cur->val) {
if (!first) first = parent;
second = cur;
}
parent = cur;
cur = cur->right;
} else {
pre = cur->left;
while (pre->right && pre->right != cur) pre = pre->right;
if (!pre->right) {
pre->right = cur;
cur = cur->left;
} else {
pre->right = NULL;
if (parent->val > cur->val) {
if (!first) first = parent;
second = cur;
}
parent = cur;
cur = cur->right;
}
}
}
if (first && second) swap(first->val, second->val);
}
};

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

  1. Java实现 LeetCode 99 恢复二叉搜索树

    99. 恢复二叉搜索树 二叉搜索树中的两个节点被错误地交换. 请在不改变其结构的情况下,恢复这棵树. 示例 1: 输入: [1,3,null,null,2] 1 / 3 \ 2 输出: [3,1,nu ...

  2. Leetcode 99.恢复二叉搜索树

    恢复二叉搜索树 二叉搜索树中的两个节点被错误地交换. 请在不改变其结构的情况下,恢复这棵树. 示例 1: 输入: [1,3,null,null,2] 输出: [3,1,null,null,2] 示例  ...

  3. 【1】【leetcode-99】 恢复二叉搜索树

    (没思路) 99. 恢复二叉搜索树 二叉搜索树中的两个节点被错误地交换. 请在不改变其结构的情况下,恢复这棵树. 示例 1: 输入: [1,3,null,null,2]   1   /  3   \ ...

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

    LeetCode:验证二叉搜索树[98] 题目描述 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当 ...

  5. Leetcode:235. 二叉搜索树的最近公共祖先

    Leetcode:235. 二叉搜索树的最近公共祖先 Leetcode:235. 二叉搜索树的最近公共祖先 Talk is cheap . Show me the code . /** * Defin ...

  6. Leetcode:530. 二叉搜索树的最小绝对差

    Leetcode:530. 二叉搜索树的最小绝对差 Leetcode:530. 二叉搜索树的最小绝对差 Talk is cheap . Show me the code . /** * Definit ...

  7. 【遍历二叉树】07恢复二叉搜索树【Recover Binary Search Tree】

    开一个指针数组,中序遍历这个二叉搜索树,将节点的指针依次保存在数组里, 然后寻找两处逆序的位置, 中序便利里BST得到的是升序序列 ++++++++++++++++++++++++++++++++++ ...

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

    题目链接 https://leetcode.com/problems/convert-bst-to-greater-tree/description/ 题目描述 大于它的节点值之和. 例如: 输入: ...

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

    669. 修剪二叉搜索树 669. Trim a Binary Search Tree 题目描述 LeetCode LeetCode669. Trim a Binary Search Tree简单 J ...

随机推荐

  1. 域scope 介绍,及查找数据

    书中介绍<jsp:useBean> 中属性 scope:   <%@ page language="java" pageEncoding="UTF-8& ...

  2. imooc-free

    前端性能优化-通用的缓存SDK 依赖项 1.在hosts文件中配置  127.0.0.1 http://cc.imooc.com   就可以直接访问 http://cc.imooc.com:3000 ...

  3. 自动安装gulpfile中所有依赖的模块

    在gulpfile.js中定义任务的时候,需要引用不同的模块,这些模块需要使用 npm install --save-dev 命令进行安装,非常的繁琐.可以使用一个名为gulpfile-install ...

  4. openstack Q版部署-----网络服务(neutron)安装部署(7)

    一.数据库配置(控制节点) 控制节点创建数据库: CREATE DATABASE neutron; GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'lo ...

  5. hadoop-1.2.1集群搭建

    继续上一篇:http://www.cnblogs.com/CoolJayson/p/7430654.html 首先需要安装上台虚拟机, 分别为: master, salve1, slave2 1.复制 ...

  6. Python3-递归函数

    什么是递归? 递归,就是函数在运行的过程中调用自己. 代码示例 def recursion(n): print(n) recursion(n+) recursion() 出现的效果就是,这个函数在不断 ...

  7. python下载夏目友人帳

    python下载夏目友人帐 一般情况下我们使用爬虫更多的应该是爬数据或者图片吧,今天在这里和大家分享一下关于使用爬虫技术来进行视频下载的方法,不仅可以方便的下载一些体积小的视频,针对大容量的视频下载同 ...

  8. 二层环路保护,RRPP多环的配置

    作者:邓聪聪 组网需求: 局域网中,由A/B/C/D构成RRPP域1换网络结构,要求环网机构中的任意两条线路中断都不能影响业务. 配置思路: 环路由两部分组成,ring1.ring2,B为环1的主节点 ...

  9. CAD版本 注册表信息

      AutoCAD2002 AutoCAD.Application.15 AutoCAD2003 AutoCAD.Application.15.1 AutoCAD2004 AutoCAD.Applic ...

  10. 题解-POI2009 WSP-Island

    Problem bzoj1137 题意概要:给定一个凸多边形坐标.点按顺时针编号 \(1\) 到 \(n\).任意两点之间都有一条长度为欧氏距离的边相连.边相交处可以自由穿行.有 \(m\) 条边不能 ...