每天一道LeetCode-----二叉搜索树的某两个节点被交换位置,修正这个二叉搜索树
生活随笔
收集整理的這篇文章主要介紹了
每天一道LeetCode-----二叉搜索树的某两个节点被交换位置,修正这个二叉搜索树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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,4,5,2,可以發現最后應該找到的節點是指向6的和指向2的節點
這兩個節點不滿足遞增關系,因為
- 6 >= 3,6是第一個節點指向的值
- 5 >= 2,2是第二個節點指向的值
- 交換兩個節點指向的值
所以,為了易于比較,需要保存上一個節點,即總共需要三個指針
- prevNode,保存上一次遍歷的節點
- firstNode,記錄找到的第一個節點
- secondNode,記錄找到的第二個節點
不過對于第一個節點,它沒有上一個節點,所以prevNode初始化不應該是nullptr,而是設定一個保存最小整數值的節點,即
TreeNode minNode(INT_MIN); prevNode = &minNode;至此,只需要在中序遍歷的時候對prevNode,firstNode,secondNode這三個節點進行更新
代碼如下
/*** 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)的不容易想到
總結
以上是生活随笔為你收集整理的每天一道LeetCode-----二叉搜索树的某两个节点被交换位置,修正这个二叉搜索树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天一道LeetCode-----对表达
- 下一篇: 每天一道LeetCode-----判断两