leetcode--99. 恢复二叉搜索树(dfs)
记录
0:10 2024-2-2
https://leetcode.cn/problems/recover-binary-search-tree
==做了好久没做出来看的题解做的。
分析原因:对dfs还是不够熟悉,特别是涉及到前/中/后序遍历的性质上
因为对二叉搜索树中序遍历得到的结果必然是非递减的,所以找到不合格的地方就行了。
如果是相邻两个数交换,如\(a_i > a_{i+1}\) 那么 nums[i], nums[j+1]就是需要交换的数
如果是间隔的两个数交换,会导致\(a_i > a_{i+1} 和 a_j > a_{j+1} (j - i > 1)\) 那么 nums[i], nums[j+1]就是需要交换的数
1.简单做法就是dfs遍历找到不对的数进行交换
2.不需要显式中序遍历找到不对的数,需要利用栈来迭代,并且每次记住上次的值用于比较
3.Morris 中序遍历
简单做法
点击查看代码
//找到不同顺序数
std::pair<int, int> findDiffOrder(vector<int> nums) {
int err1 = -1, err2 = -1;
for(int i = 0; i < nums.size() - 1; i++) {
if(nums[i] > nums[i + 1]) {
if(err1 == -1) err1 = i;
else err2 = i + 1;
}
}
if(err2 == -1) err2 = err1 + 1;
return make_pair(nums[err1], nums[err2]);
}
void inOrder(TreeNode* root, vector<int>& nums) {
if(root == nullptr) return;
inOrder(root->left, nums);
nums.push_back(root->val);
inOrder(root->right, nums);
}
void solve(TreeNode* root, std::pair<int, int> diff) {
if(root == nullptr) return;
if(root->val == diff.first) root->val = diff.second;
else if(root->val == diff.second) root->val = diff.first;
solve(root->left, diff);
solve(root->right, diff);
}
void recoverTree(TreeNode* root) {
vector<int> nums;
inOrder(root, nums);
std::pair<int, int> diff = findDiffOrder(nums);
solve(root, diff);
}
这里是迭代的方式,把一个节点左子树的最右节点的右连接到root上,其实是不用栈的中序遍历方法
中序遍历(递归实现) ===>
中序遍历(迭代实现 利用栈 第二次遇见节点的时候利用节点数据) 可以参考数据结构学习第十三天里的前/中/后序遍历输出部分 ===>
Morris中序遍历(迭代实现 不利用栈 也是第二次遇见节点的时候利用节点数据 这里是利用predecessor的右孩子不为空表示第二次遇到节点)
Morris 中序遍历
点击查看代码
void inOrder() {
TreeNode *x = nullptr, *y = nullptr, *pred = nullptr, *predecessor = nullptr;
while (root != nullptr) {
if (root->left != nullptr) {
// predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
predecessor = root->left;
while (predecessor->right != nullptr && predecessor->right != root) {
predecessor = predecessor->right;
}
// 让 predecessor 的右指针指向 root,继续遍历左子树
if (predecessor->right == nullptr) {
predecessor->right = root;
root = root->left;
}
// 说明左子树已经访问完了,我们需要断开链接
else {
if (pred != nullptr && root->val < pred->val) {
y = root;
if (x == nullptr) {
x = pred;
}
}
pred = root;
predecessor->right = nullptr;
root = root->right;
}
}
// 如果没有左孩子,则直接访问右孩子
else {
pred = root;
root = root->right;
}
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/recover-binary-search-tree/solutions/365385/hui-fu-er-cha-sou-suo-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处