【Recover Binary Search Tree】cpp
题目:
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?
confused what "{1,#,2,3}"
means? > read more on how binary tree is serialized on OJ.
代码:
/** * 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) { if (!root) return; TreeNode *pre, *curr, *first=NULL, *second=NULL; stack<TreeNode *> sta; TreeNode *dummy = new TreeNode(INT_MIN); dummy->left = root; pre = dummy; curr = root; while ( !sta.empty() || curr ) { if (curr){ sta.push(curr); curr = curr->left; } else{ curr = sta.top(); sta.pop(); if ( !first ){ if ( pre->val > curr->val ){ first = pre; second = curr; } } else{ if ( curr->val < pre->val ){ second = curr; break; } } pre = curr; curr = curr->right; } } std::swap(first->val, second->val); } };
tips:
二叉查找树的中序遍历就是从小到大的输出(http://zh.wikipedia.org/wiki/二元搜尋樹)。
即从中序遍历的结果中找到两个需要交换的点。
为了简便,这里设定了虚根节点(初始化值为INT_MIN)保证不影响中序遍历的结果。具体的思想都参考的(http://www.cnblogs.com/TenosDoIt/p/3445682.html)。
通过这道题回顾了一下中序遍历的方法,并纠正了之前的中序遍历的一种自毁型的代码
http://www.cnblogs.com/xbf9xbf/p/4501655.html
在上面这道题中,写了一个自毁型的中序遍历代码(即中序遍历结束后,整个二叉树的所有节点都断了)。
在本道题中一开始沿用了这种自毁型的中序遍历代码,结果就可想而知了。通过这个点,给自己提个醒:以后再涉及到遍历这类的代码,尽量不要再写这种遍历一次就毁坏了数据结构的代码了。
===========================================
第二次过这道题,直接学习的原来的代码。AC之后弄清楚了两个点:
(1)中序遍历是个模板,对BST的操作很多都依赖中序遍历。所以不管有没有first和second都要注意把中序遍历的代码写全了
(2)为什么找到第一个是first=pre而找到第二个是second=curr呢?曾就这个问题纠结过,后来猜测背后的思路可能是这样的:
由于BST的两个节点位置错乱了,那么中序遍历必然有前面的节点要大于后面的。因此找到第一个不符合BST条件的,pre肯定是first;找到第二个不符合条件的curr肯定是second。
另外还有一种特殊情况,就是被错位的两个点是挨着的,这样就更直接了。pre肯定是frist,curr肯定是second。
/** * 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) { stack<TreeNode*> sta; TreeNode* first=NULL; TreeNode* second=NULL; TreeNode dummpy(INT_MIN); dummpy.left = root; TreeNode* pre = &dummpy; TreeNode* curr = root; while ( !sta.empty() || curr ) { if ( curr ) { sta.push(curr); curr = curr->left; } else { curr = sta.top(); sta.pop(); if ( !first ) { if (curr->val<pre->val) { first = pre; second = curr; } } else { if ( curr->val<pre->val) { second = curr; break; } } pre = curr; curr = curr->right; } } std::swap(first->val, second->val); } };
============================================================
第三次过这道题,本来不想粘代码了,但前几次的代码实在太冗余了,于是贴一版新的。
/** * 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) { stack<TreeNode*> sta; TreeNode *pre = new TreeNode(INT_MIN); TreeNode *curr = root; TreeNode *n1=NULL, *n2=NULL; while ( !sta.empty() || curr ) { if ( curr ) { sta.push(curr); curr = curr->left; } else { curr = sta.top(); sta.pop(); if ( pre->val > curr->val ) { if ( !n1 ) { n1 = pre; n2 = curr; } else { n2 = curr; break; } } pre = curr; curr = curr->right; } } if (n1) swap(n1->val, n2->val); } };