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++解法一:
// 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):恢复二叉搜索树的更多相关文章
- Java实现 LeetCode 99 恢复二叉搜索树
99. 恢复二叉搜索树 二叉搜索树中的两个节点被错误地交换. 请在不改变其结构的情况下,恢复这棵树. 示例 1: 输入: [1,3,null,null,2] 1 / 3 \ 2 输出: [3,1,nu ...
- Leetcode 99.恢复二叉搜索树
恢复二叉搜索树 二叉搜索树中的两个节点被错误地交换. 请在不改变其结构的情况下,恢复这棵树. 示例 1: 输入: [1,3,null,null,2] 输出: [3,1,null,null,2] 示例 ...
- 【1】【leetcode-99】 恢复二叉搜索树
(没思路) 99. 恢复二叉搜索树 二叉搜索树中的两个节点被错误地交换. 请在不改变其结构的情况下,恢复这棵树. 示例 1: 输入: [1,3,null,null,2] 1 / 3 \ ...
- LeetCode:验证二叉搜索树【98】
LeetCode:验证二叉搜索树[98] 题目描述 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当 ...
- Leetcode:235. 二叉搜索树的最近公共祖先
Leetcode:235. 二叉搜索树的最近公共祖先 Leetcode:235. 二叉搜索树的最近公共祖先 Talk is cheap . Show me the code . /** * Defin ...
- Leetcode:530. 二叉搜索树的最小绝对差
Leetcode:530. 二叉搜索树的最小绝对差 Leetcode:530. 二叉搜索树的最小绝对差 Talk is cheap . Show me the code . /** * Definit ...
- 【遍历二叉树】07恢复二叉搜索树【Recover Binary Search Tree】
开一个指针数组,中序遍历这个二叉搜索树,将节点的指针依次保存在数组里, 然后寻找两处逆序的位置, 中序便利里BST得到的是升序序列 ++++++++++++++++++++++++++++++++++ ...
- Leetcode 538. 把二叉搜索树转换为累加树
题目链接 https://leetcode.com/problems/convert-bst-to-greater-tree/description/ 题目描述 大于它的节点值之和. 例如: 输入: ...
- LeetCode 669. 修剪二叉搜索树(Trim a Binary Search Tree)
669. 修剪二叉搜索树 669. Trim a Binary Search Tree 题目描述 LeetCode LeetCode669. Trim a Binary Search Tree简单 J ...
随机推荐
- LOJ #2026「JLOI / SHOI2016」成绩比较
很好的锻炼推柿子能力的题目 LOJ #2026 题意 有$n$个人$ m$门学科,第$ i$门的分数为不大于$U_i$的一个正整数 定义A「打爆」B当且仅当A的每门学科的分数都不低于B的该门学科的分数 ...
- jq的遍历关系元素方法集合
children .children(selector) 返回被选元素的所有直接子元素,不返回文本节点: 下面例子:给level-2的子元素设置border.比较使用children和find htm ...
- 【mmall】url-pattern配置为"/"和"/*"的区别
我的代码 <!-- springmvc --> <servlet> <servlet-name>springmvc</servlet-name> < ...
- 将List的元素通过中文字符串排序
类customer public class Customer { public String name; public int age; Customer(String name, int age) ...
- i春秋 小漏洞也有大梦想
i春秋上的课,提到了一些概念,学习并记录. 此文主要以了解概念为主,没有代码和实战. 水坑式攻击 百度定义: “水坑式攻击”,是指黑客通过分析被攻击者的网络活动规律,寻找被攻击者经常访问的网站的弱点, ...
- 省电优化之WakeLock
https://blog.csdn.net/qfanmingyiq/article/details/54587664 boolean onStopJob (JobParameters params) ...
- php编程 之 php基础三
1,php里的while循环 循环执行代码块指定的次数,或者当指定的条件为真时循环执行代码块. while实例: <html> <body> <?php $i=1; wh ...
- RabbitMQ应用场景
1.背景 RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现. 2.应用场景 2.1异步处理 场景说明:用户注册后,需要发注册邮件和注册短信, ...
- How to Train Triplet Networks with 100K Identities?
1. 为什么介绍此文? Triplet net 改进工作之一,主要思想是在大数据集(人脸识别)上的困难样本挖掘.人脸识别工作对于图像对匹配而言很有借鉴意义,共性是特征的提取和样本数据的挖掘. Trip ...
- requests支持socks5代理了
记录下 以前: import socket import socks from requests_html import HTMLSession session=HTMLSession() socks ...