每天一道LeetCode-----二叉搜索树的某两个节点被交换位置,修正这个二叉搜索树
来源:互联网 发布:淘宝美工将来有前途么 编辑:程序博客网 时间:2024/06/05 19:38
Recover Binary Search Tree
原题链接Recover Binary Search Tree
给定一个二叉搜索树(BST),但是树中有两个节点被交换了,找到这两个节点,将其修正
二叉搜索树规则
- 当前节点的值大于左子树的所有节点值
- 当前节点的值小于右子树的所有节点值
- 左右子树同样是二叉搜索树
对于二叉搜索树,如果进行中序遍历,那么得到的序列一定是递增的。而对于本题而言,如果使用中序遍历,那么序列中一定会有两个值影响到了递增关系
那么,只需要改变这两个值的位置,然后重新中序遍历一遍为所有节点重新赋值即可,空间复杂度为O(n)
代码如下
/** * 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: void recoverTree(TreeNode* root){ vector<int> nums; //先中序遍历把所有节点值找到 inOrder(root, nums); //排序,修正节点值顺序 std::sort(nums.begin(), nums.end()); int i = 0; //在中序遍历一遍,重新为节点赋值 recover(root, nums, i); }private: void inOrder(TreeNode* root, vector<int>& nums) { if(!root) return; inOrder(root->left, nums); nums.emplace_back(root->val); inOrder(root->right, nums); } void recover(TreeNode* root, vector<int>& nums, int& i) { if(!root) return; recover(root->left, nums, i); root->val = nums[i++]; recover(root->right, nums, i); }};
当然,为了优化空间复杂度,可以直接在中序遍历修改节点的值,假设中序遍历的结果是
这两个节点不满足递增关系,因为
- 6 >= 3,6是第一个节点指向的值
- 5 >= 2,2是第二个节点指向的值
- 交换两个节点指向的值
所以,为了易于比较,需要保存上一个节点,即总共需要三个指针
- prevNode,保存上一次遍历的节点
- firstNode,记录找到的第一个节点
- secondNode,记录找到的第二个节点
不过对于第一个节点,它没有上一个节点,所以prevNode初始化不应该是nullptr,而是设定一个保存最小整数值的节点,即
TreeNode minNode(INT_MIN);prevNode = &minNode;
至此,只需要在中序遍历的时候对
代码如下
/** * 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: void recoverTree(TreeNode* root){ TreeNode minNode(INT_MIN); //仅仅是为了不用new TreeNode(INT_MIN); prevNode = &minNode; firstNode = secondNode = nullptr; recover(root); swap(firstNode->val, secondNode->val); }private: void recover(TreeNode* root) { if(!root) return; recover(root->left); //prevNode记录上一个节点 //当上一个节点的值大于当前节点值时,说明上一个节点是错误的,影响了递增 //因为递增的时候只能大的值跑到前面导致错误,所以prevNode是错误的 if(!firstNode && prevNode->val >= root->val) firstNode = prevNode; //当firstNode记录完后,当前节点小于前面的节点,说明当前节点是错误的 //因为递增的时候只能是小的值跑到后面导致错误,所以root是错误的 if(firstNode && prevNode->val >= root->val) secondNode = root; //改变上一个节点,继续寻找 prevNode = root; recover(root->right); }private: TreeNode* prevNode; TreeNode* firstNode; TreeNode* secondNode;};
本题主要是中序遍历的问题,解决思路是在中序遍历中进行更改,两边遍历的方法比较容易想到,但是O(1)的不容易想到
阅读全文