其他LeetCode题目欢迎访问:LeetCode结题报告索引
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
分析:首先我们最直观的的想法是中序遍历得到中序序列,平衡二叉树的中序序列是非递减有序的。那么问题就转化成了在非递减有序序列中交换了两个数的位置,找出这两个数并恢复有序序列,这个问题可以通过遍历一遍有序序列分下面2步完成:
- 首先找到第一个错误的数first,即第一个比它后缀要大的数
- 然后要找到第一个错误的数应该放置的位置(这就是第二个错误的数),即要找到第一个比first大的数的前驱,这个前驱就是第一个错误的数应该放的位置,也就是第二个错误的数。(注意一个特殊情况{0,1},first为1,没有找到比first大的数,这是second就是最后一个数0)
算法1:我们可以用递归中序遍历(或者使用栈的非递归中序遍历)来实现,但是这样空间复杂度都是O(n)。下面代码是递归中序遍历,可以通过oj
1 /** 2 * Definition for binary tree 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 * }; 9 */ 10 class Solution { 11 public: 12 void recoverTree(TreeNode *root) { 13 // IMPORTANT: Please reset any member data you declared, as 14 // the same Solution instance will be reused for each test case. 15 TreeNode *pre = NULL, *first = NULL, *second = NULL; 16 inorder(root, pre, first, second); 17 if(first != NULL) 18 { 19 if(second == NULL)second = pre;//树{0,1}就可能出现这种情况 20 int tmp = first->val; 21 first->val = second->val; 22 second->val = tmp; 23 } 24 } 25 //pre是中序序列中当前节点的前驱,first、second分别是要找的两个乱序节点 26 void inorder(TreeNode *root, TreeNode* &pre, TreeNode* &first, TreeNode* &second) 27 { 28 if(root == NULL)return; 29 if(root->left)inorder(root->left, pre, first, second); 30 if(pre != NULL) 31 { 32 if(first == NULL && root->val < pre->val) 33 first = pre; 34 else if(first && root->val > first->val) 35 {second = pre; return;}//两个错误位置都找到就退出 36 } 37 pre = root; 38 if(root->right)inorder(root->right, pre, first, second); 39 } 40 };