1. 程式人生 > >Leetcode:99.恢復二叉搜尋樹

Leetcode:99.恢復二叉搜尋樹

二叉搜尋樹中的兩個節點被錯誤地交換。請在不改變其結構的情況下,恢復這棵樹。

示例 1:

輸入: [1,3,null,null,2]

   1
  /
 3
  \
   2

輸出: [3,1,null,null,2]

   3
  /
 1
  \
   2

示例 2:

輸入: [3,1,4,null,null,2]

  3
 / \
1   4
   /
  2

輸出: [2,1,4,null,null,3]

  2
 / \
1   4
   /
  3

解題思路:

二叉搜尋樹:中序遍歷中沒有逆序對。如果知道什麼是中序遍歷,還有二叉搜尋樹,本題只能算是easy。

按照題意只交換了二叉樹的兩個結點,這也就意味著是排序陣列中交換了兩個元素的位置,這麼一想就會變得容易很多。

1. 交換的兩個元素中序遍歷相鄰。這時只會出現一個逆序對,交換兩個逆序對結點的的val即可。

2. 兩個元素在中序遍歷陣列中不相鄰。會出現兩個逆序對,我們只需記錄第一個逆序對的第一個結點,以及第二個逆序對的第二個結點即可,最後交換兩個結點的val即可。

只需要記錄逆序對的位置即可,因此僅用了常數個空間。

                        

C++程式碼
#define hasLChild(x) (!(x->left==NULL))
#define hasRChild(x) (!(x->right==NULL))
class Solution {
 public:
     void recoverTree(TreeNode* root) {
         //中序遍歷
         In_order_traversal(root);
         swap(first->val, second->val);
     }
     void In_order_traversal(TreeNode* root) {
         if (sgn == 2) return;
         if (hasLChild(root)) In_order_traversal(root->left);
         if (temp == NULL) temp = root;
         else {
             if (temp->val > root->val) {//出現了逆序對
                 if (sgn == 0) { first = temp; second = root; sgn = 1; }
                 else { second = root; sgn = 2; }
             }
             temp = root;
         }
         if (hasRChild(root)) In_order_traversal(root->right);
     }
 private:
     TreeNode* temp = NULL;
     TreeNode* first, *second;
     int sgn = 0;
 };