[LeetCode] 99. 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] 3
/ \
1 4
/
2 Output: [2,1,4,null,null,3] 2
/ \
1 4
/
3
Follow up:
- A solution using O(n) space is pretty straight forward.
- Could you devise a constant space solution?
这道题要求我们复原一个二叉搜索树,说是其中有两个的顺序被调换了,题目要求上说 O(n) 的解法很直观,这种解法需要用到递归,用中序遍历树,并将所有节点存到一个一维向量中,把所有节点值存到另一个一维向量中,然后对存节点值的一维向量排序,在将排好的数组按顺序赋给节点。这种最一般的解法可针对任意个数目的节点错乱的情况,这里先贴上此种解法:
解法一:
// 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为树的高度,参见代码如下:
解法二:
// Still O(n) space complexity
class Solution {
public:
TreeNode *pre = NULL, *first = NULL, *second = NULL;
void recoverTree(TreeNode* root) {
inorder(root);
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);
}
};
我们其实也可以使用迭代的写法,因为中序遍历 Binary Tree Inorder Traversal 也可以借助栈来实现,原理还是跟前面的相同,记录前一个结点,并和当前结点相比,如果前一个结点值大,那么更新 first 和 second,最后交换 first 和 second 的结点值即可,参见代码如下:
解法三:
// Always O(n) space complexity
class Solution {
public:
void recoverTree(TreeNode* root) {
TreeNode *pre = NULL, *first = NULL, *second = NULL, *p = root;
stack<TreeNode*> st;
while (p || !st.empty()) {
while (p) {
st.push(p);
p = p->left;
}
p = st.top(); st.pop();
if (pre) {
if (pre->val > p->val) {
if (!first) first = pre;
second = p;
}
}
pre = p;
p = p->right;
}
swap(first->val, second->val);
}
};
这道题的真正符合要求的解法应该用的 Morris 遍历,这是一种非递归且不使用栈,空间复杂度为 O(1) 的遍历方法,可参见博主之前的博客 Binary Tree Inorder Traversal,在其基础上做些修改,加入 first, second 和 parent 指针,来比较当前节点值和中序遍历的前一节点值的大小,跟上面递归算法的思路相似,代码如下:
解法四:
// Now O(1) space complexity
class Solution {
public:
void recoverTree(TreeNode* root) {
TreeNode *first = nullptr, *second = nullptr, *cur = root, *pre = nullptr ;
while (cur) {
if (cur->left){
TreeNode *p = cur->left;
while (p->right && p->right != cur) p = p->right;
if (!p->right) {
p->right = cur;
cur = cur->left;
continue;
} else {
p->right = NULL;
}
}
if (pre && cur->val < pre->val){
if (!first) first = pre;
second = cur;
}
pre = cur;
cur = cur->right;
}
swap(first->val, second->val);
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/99
类似题目:
参考资料:
https://leetcode.com/problems/recover-binary-search-tree/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 99. Recover Binary Search Tree 复原二叉搜索树的更多相关文章
- [leetcode]99. Recover Binary Search Tree恢复二叉搜索树
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...
- [LeetCode] Recover Binary Search Tree 复原二叉搜索树
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...
- 099 Recover Binary Search Tree 复原二叉搜索树
二叉排序树中有两个节点被交换了,要求把树恢复成二叉排序树. 详见:https://leetcode.com/problems/recover-binary-search-tree/submission ...
- [LeetCode] 99. Recover Binary Search Tree(复原BST) ☆☆☆☆☆
Recover Binary Search Tree leetcode java https://leetcode.com/problems/recover-binary-search-tree/di ...
- [Leetcode] Recover binary search tree 恢复二叉搜索树
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...
- [LeetCode] 98. Validate Binary Search Tree 验证二叉搜索树
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...
- [leetcode]98. Validate Binary Search Tree验证二叉搜索树
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...
- [CareerCup] 4.5 Validate Binary Search Tree 验证二叉搜索树
4.5 Implement a function to check if a binary tree is a binary search tree. LeetCode上的原题,请参见我之前的博客Va ...
- leetcode 99 Recover Binary Search Tree ----- java
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...
随机推荐
- 普通的行专列;oracle行专列;更新中。。。
题记 本来想写一个完整的表创建,但是其他人都写过啦,要不这样,你们有什么行转列的问题给我留言,我直接回答如何 Oracle的行转列 这篇文章不错:https://blog.csdn.net/huay_ ...
- Map映射如何使用迭代器?
迭代器只针对集合类型的数据,因此map类型的必须先转换成集合类型才能使用迭代器去获取元素. 1.在map中虽然不能直接实例化迭代器,但map集合提供了keySet()方法和value()方法,可以通过 ...
- 常见的几种 Normalization 算法
神经网络中有各种归一化算法:Batch Normalization (BN).Layer Normalization (LN).Instance Normalization (IN).Group No ...
- idea 项目在一般模式下可以正常启动,在debug模式下无法启动,像是卡住了的感觉
项目一般模式下可以启动,debug模式下就是启动不了,后经过排查发现打的有断点,断点取消在重启立马就可以啦. Method breakpoints may dramatically slow down ...
- C#中文转换为拼音NPinyin代码【转】
项目地址:https://code.google.com/p/npinyin/ 在一个采集的程序中,为了给每个文章起一个别名,据说有很好的别名的话,对于百度.google的收录 是很有好处的.按照Se ...
- Kubernetes Ingress 部署
Kubernetes Ingress 部署 Pod与Ingress的关系• 通过service相关联• 通过Ingress Controller实现Pod的负载均衡- 支持TCP/UDP 4层和HTT ...
- Kubernetes DaemonSet(部署守护进程)
Kubernetes DaemonSet(部署守护进程) • 在每一个Node上运行一个Pod• 新加入的Node也同样会自动运行一个Pod 应用场景:Agent 官方文档:https://kuber ...
- DVWA-CSRF学习笔记
DVWA-CSRF学习笔记 一.CSRF(跨站请求伪造) CSRF(跨站请求伪造),是指利用受害者尚未失效的身份认证信息(cookie.session会话等),诱骗其点击恶意链接或者访问包含攻击代码的 ...
- ExcelHelper based on NPOI
//Export data to excel via NPOI public static void ExportDataTableToExcel(DataTable dataTable, strin ...
- ASP.NET Core系列:依赖注入
1. 控制反转(IoC) 控制反转(Inversion of Control,IoC),是面向对象编程中的一种设计原则,用来降低代码之间的耦合度. 1.1 依赖倒置 依赖原则: (1)高层次的模块不应 ...