1. 程式人生 > >[LeetCode] Minimum Absolute Difference in BST 二叉搜尋樹的最小絕對差

[LeetCode] Minimum Absolute Difference in BST 二叉搜尋樹的最小絕對差

Given a binary search tree with non-negative values, find the minimum absolute difference between values of any two nodes.

Example:

Input:

   1
    \
     3
    /
   2

Output:
1

Explanation:
The minimum absolute difference is 1, which is the difference between 2 and 1 (or between 2 and 3).

Note: There are at least two nodes in this BST.

這道題給了我們一棵二叉搜尋樹,讓我們求任意個節點值之間的最小絕對差。由於BST的左<根<右的性質可知,如果按照中序遍歷會得到一個有序陣列,那麼最小絕對差肯定在相鄰的兩個節點值之間產生。所以我們的做法就是對BST進行中序遍歷,然後當前節點值和之前節點值求絕對差並更新結果res。這裡需要注意的就是在處理第一個節點值時,由於其沒有前節點,所以不能求絕對差。這裡我們用變數pre來表示前節點值,這裡由於題目中說明了所以節點值不為負數,所以我們給pre初始化-1,這樣我們就知道pre是否存在。如果沒有題目中的這個非負條件,那麼就不能用int變數來,必須要用指標,通過來判斷是否為指向空來判斷前結點是否存在。還好這裡簡化了問題,用-1就能搞定了,這裡我們先來看中序遍歷的遞迴寫法,參見程式碼如下:

解法一:

class Solution {
public:
    int getMinimumDifference(TreeNode* root) {
        int res = INT_MAX, pre = -1;
        inorder(root, pre, res);
        return res;
    }
    void inorder(TreeNode* root, int& pre, int& res) {
        if (!root) return;
        inorder(root->left, pre, res);
        
if (pre != -1) res = min(res, root->val - pre); pre = root->val; inorder(root->right, pre, res); } };

其實我們也不必非要用中序遍歷不可,用先序遍歷同樣可以利用到BST的性質,我們帶兩個變數low和high來分別表示上下界,初始化為int的極值,然後我們在遞迴函式中,分別用上下界和當前節點值的絕對差來更新結果res,參見程式碼如下:

解法二:

class Solution {
public:
    int getMinimumDifference(TreeNode* root) {
        int res = INT_MAX;
        helper(root, INT_MIN, INT_MAX, res);
        return res;
    }
    void helper(TreeNode* root, int low, int high, int& res) {
        if (!root) return;
        if (low != INT_MIN) res = min(res, root->val - low);
        if (high != INT_MAX) res = min(res, high - root->val);
        helper(root->left, low, root->val, res);
        helper(root->right, root->val, high, res);
    }
};

下面這種方法是解法一的迭代的寫法,思路跟之前的解法沒有什麼區別,參見程式碼如下:

解法三:

class Solution {
public:
    int getMinimumDifference(TreeNode* root) {
        int res = INT_MAX, pre = -1;
        stack<TreeNode*> st;
        TreeNode *p = root;
        while (p || !st.empty()) {
            while (p) {
                st.push(p);
                p = p->left;
            }
            p = st.top(); st.pop();
            if (pre != -1) res = min(res, p->val - pre);
            pre = p->val;
            p = p->right;
        }
        return res;
    }
};

參考資料: