1. 程式人生 > >[LeetCode] Trim a Binary Search Tree 修剪一棵二叉搜尋樹

[LeetCode] Trim a Binary Search Tree 修剪一棵二叉搜尋樹

Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so that all its elements lies in [L, R] (R >= L). You might need to change the root of the tree, so the result should return the new root of the trimmed binary search tree.

Example 1:

Input: 
    1
   / \
  0   2

  L = 1
  R = 2

Output: 
    1
      \
       2

Example 2:

Input: 
    3
   / \
  0   4
   \
    2
   /
  1

  L = 1
  R = 3

Output: 
      3
     / 
   2   
  /
 1

這道題讓我們修剪一棵二叉搜尋樹,給了個邊界範圍[L, R], 所有不在這個範圍內的結點應該被移除掉,但是仍需要保留二叉搜尋樹的性質,即左<根<右,有時候是小於等於。博主最開始的想法是先遍歷一遍二叉樹,將在返回內的結點值都放到一個數組後,遍歷結束後再根據陣列重建一棵二叉搜尋樹。這種方法會在某些test case上fail掉,可能會改變原來的二叉搜尋樹的結構,所以我們只能換一種思路。正確方法其實應該是在遍歷的過程中就修改二叉樹,移除不合題意的結點。當然對於二叉樹的題,十有八九都是要用遞迴來解的。首先判斷如果root為空,那麼直接返回空即可。然後就是要看根結點是否在範圍內,如果根結點值小於L,那麼返回對其右子結點呼叫遞迴函式的值;如果根結點大於R,那麼返回對其左子結點呼叫遞迴函式的值。如果根結點在範圍內,將其左子結點更新為對其左子結點呼叫遞迴函式的返回值,同樣,將其右子結點更新為對其右子結點呼叫遞迴函式的返回值。最後返回root即可,參見程式碼如下:

解法一:

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int L, int R) {
        if (!root) return NULL;
        if (root->val < L) return trimBST(root->right, L, R);
        if (root->val > R) return trimBST(root->left, L, R);
        root->left = trimBST(root->left, L, R);
        root
->right = trimBST(root->right, L, R); return root; } };

下面這種方法是迭代的寫法,雖然樹的題一般都是用遞迴來寫,簡潔又美觀。但是我們也可以強行用while來代替遞迴,比如下面這種寫法:

解法二:

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int L, int R) {
        if (!root) return NULL;
        while (root->val < L || root->val > R) {
            root = (root->val < L) ? root->right : root->left;
        }
        TreeNode *cur = root;
        while (cur) {
            while (cur->left && cur->left->val < L) {
                cur->left = cur->left->right;
            }
            cur = cur->left;
        }
        cur = root;
        while (cur) {
            while (cur->right && cur->right->val > R) {
                cur->right = cur->right->left;
            }
            cur = cur->right;
        }
        return root;
    }
};

參考資料: