问题描述:
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?
解题思路:
通过上一道题学习到的解题方法:利用中序遍历啊来判断二叉树是否为一颗二叉树。
这次我也利用了中序遍历。
观察给出的两个例子:
[3,1,4,null,null,2]
中序遍历为1-3-2-4,实际应为1-2-3-4
[1,3,null,null,2]
中序遍历为3-2-1,实际应为1-2-3
因为二叉树的性质:小于节点的在左,大于节点的在右
使用中序排序得到的序列应为一个递增序列。
因为是调换了两个节点,则必然是小的跑到了后面,大的跑到了前面
我们可以利用中序遍历查找第一个大于后面的值的节点,此为被调换的第一个节点
查找小于前一个值的节点,此为第二个节点。
需要注意的是:有两个节点排序中相邻,即给出的第二个例子的情况,所以再加一个指针记录可能的第二个节点。
一定要记住移动pre!!!(我就忘了。。小声bb
代码:
/** * 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) { bool change = false; stack<TreeNode*> stk; TreeNode* pre = NULL; TreeNode* cur = root; TreeNode* t1 = NULL; TreeNode* t2 = NULL; while(cur || !stk.empty()){ while(cur){ stk.push(cur); cur = cur->left; } cur = stk.top(); stk.pop(); if(!pre) pre = cur; else{ if(cur->val < pre->val){ if(!t1){ t1 = pre; t2 = cur; } else{ int temp = cur->val; cur->val = t1->val; t1->val = temp; change = true; break; } } } pre = cur; cur = cur->right; } if(!change){ int temp = t1->val; t1->val = t2->val; t2->val = temp; } } };
看看另一种48ms解法 空间复杂度为O(n),我的为76ms:
× Close sample 48 ms submission /** * 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* 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); } };