[LeetCode] Closest Binary Search Tree Value 最近的二分搜尋樹的值
阿新 • • 發佈:2018-12-27
Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.
Note:
- Given target value is a floating point.
- You are guaranteed to have only one unique value in the BST that is closest to the target.
這道題讓我們找一個二分搜尋數的跟給定值最接近的一個節點值,由於是二分搜尋樹,所以我最先想到用中序遍歷來做,一個一個的比較,維護一個最小值,不停的更新,實際上這種方法並沒有提高效率,用其他的遍歷方法也可以,參見程式碼如下:
解法一:
class Solution { public: int closestValue(TreeNode* root, double target) { double d = numeric_limits<double>::max(); int res = 0; stack<TreeNode*> s; TreeNode *p = root; while (p || !s.empty()) { while (p) { s.push(p); p= p->left; } p = s.top(); s.pop(); if (d >= abs(target - p->val)) { d = abs(target - p->val); res = p->val; } p = p->right; } return res; } };
實際我們可以利用二分搜尋樹的特點(左<根<右)來快速定位,由於根節點是中間值,我們在往下遍歷時,我們根據目標值和根節點的值大小關係來比較,如果目標值小於節點值,則我們應該找更小的值,於是我們到左子樹去找,反之我們去右子樹找,參見程式碼如下:
解法二:
class Solution { public: int closestValue(TreeNode* root, double target) { int res = root->val; while (root) { if (abs(res - target) >= abs(root->val - target)) { res = root->val; } root = target < root->val ? root->left : root->right; } return res; } };
以上兩種方法都是迭代的方法,下面我們來看遞迴的寫法,下面這種遞迴的寫法和上面迭代的方法思路相同,都是根據二分搜尋樹的性質來優化查詢,但是遞迴的寫法用的是回溯法,先遍歷到葉節點,然後一層一層的往回走,把最小值一層一層的運回來,參見程式碼如下:
解法三:
class Solution { public: int closestValue(TreeNode* root, double target) { int a = root->val; TreeNode *t = target < a ? root->left : root->right; if (!t) return a; int b = closestValue(t, target); return abs(a - target) < abs(b - target) ? a : b; } };
再來看另一種遞迴的寫法,思路和上面的都相同,寫法上略有不同,用if來分情況,參見程式碼如下:
解法三:
class Solution { public: int closestValue(TreeNode* root, double target) { int res = root->val; if (target < root->val && root->left) { int l = closestValue(root->left, target); if (abs(res - target) >= abs(l - target)) res = l; } else if (target > root->val && root->right) { int r = closestValue(root->right, target); if (abs(res - target) >= abs(r - target)) res = r; } return res; } };
最後來看一種分治法的寫法,這種方法相當於解法一的遞迴寫法,並沒有利用到二分搜尋樹的性質來優化搜尋,參見程式碼如下:
解法四:
class Solution { public: int closestValue(TreeNode* root, double target) { double diff = numeric_limits<double>::max(); int res = 0; helper(root, target, diff, res); return res; } void helper(TreeNode *root, double target, double &diff, int &res) { if (!root) return; if (diff >= abs(root->val - target)) { diff = abs(root->val - target); res = root->val; } helper(root->left, target, diff, res); helper(root->right, target, diff, res); } };
參考資料: