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.
Example:
Input: root = [4,2,5,1,3], target = 3.714286 4 / \ 2 5 / \ 1 3 Output: 4
這道題讓我們找一個二分搜索數的跟給定值最接近的一個節點值,由於是二分搜索樹,所以博主最先想到用中序遍歷來做,一個一個的比較,維護一個最小值,不停的更新,實際上這種方法並沒有提高效率,用其他的遍歷方法也可以,參見代碼如下:
解法一:
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); } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/270
類似題目:
Closest Binary Search Tree Value II
Search in a Binary Search Tree
參考資料:
https://leetcode.com/problems/closest-binary-search-tree-value/