[LeetCode] 272. Closest Binary Search Tree Value II 最近的二分搜索树的值之二
Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target.
Note:
- Given target value is a floating point.
- You may assume k is always valid, that is: k≤ total nodes.
- You are guaranteed to have only one unique set of k values in the BST that are closest to the target.
Example:
Input: root = [4,2,5,1,3], target = 3.714286, and k = 2
4
/ \
2 5
/ \
1 3
Output: [4,3]
Follow up:
Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?
这道题是之前那道 Closest Binary Search Tree Value 的拓展,那道题只让找出离目标值最近的一个节点值,而这道题让找出离目标值最近的k个节点值,难度瞬间增加了不少,博主最先想到的方法是用中序遍历将所有节点值存入到一个一维数组中,由于二分搜索树的性质,这个一维数组是有序的,然后再在有序数组中需要和目标值最近的k个值就简单的多,参见代码如下:
解法一:
class Solution {
public:
vector<int> closestKValues(TreeNode* root, double target, int k) {
vector<int> res, v;
inorder(root, v);
int idx = ;
double diff = numeric_limits<double>::max();
for (int i = ; i < v.size(); ++i) {
if (diff >= abs(target - v[i])) {
diff = abs(target - v[i]);
idx = i;
}
}
int left = idx - , right = idx + ;
for (int i = ; i < k; ++i) {
res.push_back(v[idx]);
if (left >= && right < v.size()) {
if (abs(v[left] - target) > abs(v[right] - target)) {
idx = right;
++right;
} else {
idx = left;
--left;
}
} else if (left >= ) {
idx = left;
--left;
} else if (right < v.size()) {
idx = right;
++right;
}
}
return res;
}
void inorder(TreeNode *root, vector<int> &v) {
if (!root) return;
inorder(root->left, v);
v.push_back(root->val);
inorder(root->right, v);
}
};
还有一种解法是直接在中序遍历的过程中完成比较,当遍历到一个节点时,如果此时结果数组不到k个,直接将此节点值加入结果 res 中,如果该节点值和目标值的差值的绝对值小于结果 res 的首元素和目标值差值的绝对值,说明当前值更靠近目标值,则将首元素删除,末尾加上当前节点值,反之的话说明当前值比结果 res 中所有的值都更偏离目标值,由于中序遍历的特性,之后的值会更加的遍历,所以此时直接返回最终结果即可,参见代码如下:
解法二:
class Solution {
public:
vector<int> closestKValues(TreeNode* root, double target, int k) {
vector<int> res;
inorder(root, target, k, res);
return res;
}
void inorder(TreeNode *root, double target, int k, vector<int> &res) {
if (!root) return;
inorder(root->left, target, k, res);
if (res.size() < k) res.push_back(root->val);
else if (abs(root->val - target) < abs(res[] - target)) {
res.erase(res.begin());
res.push_back(root->val);
} else return;
inorder(root->right, target, k, res);
}
};
下面这种方法是上面那种方法的迭代写法,原理一模一样,参见代码如下:
解法三:
class Solution {
public:
vector<int> closestKValues(TreeNode* root, double target, int k) {
vector<int> res;
stack<TreeNode*> s;
TreeNode *p = root;
while (p || !s.empty()) {
while (p) {
s.push(p);
p = p->left;
}
p = s.top(); s.pop();
if (res.size() < k) res.push_back(p->val);
else if (abs(p->val - target) < abs(res[] - target)) {
res.erase(res.begin());
res.push_back(p->val);
} else break;
p = p->right;
}
return res;
}
};
在来看一种利用最大堆来解题的方法,堆里保存的一个差值 diff 和节点值的 pair,中序遍历二叉树(也可以用其他遍历方法),然后对于每个节点值都计算一下和目标值之差的绝对值,由于最大堆的性质,diff 大的自动拍到最前面,维护k个 pair,如果超过了k个,就把堆前面大的 pair 删掉,最后留下的k个 pair,将 pair 中的节点值取出存入结果 res 中返回即可,参见代码如下:
解法四:
class Solution {
public:
vector<int> closestKValues(TreeNode* root, double target, int k) {
vector<int> res;
priority_queue<pair<double, int>> q;
inorder(root, target, k, q);
while (!q.empty()) {
res.push_back(q.top().second);
q.pop();
}
return res;
}
void inorder(TreeNode *root, double target, int k, priority_queue<pair<double, int>> &q) {
if (!root) return;
inorder(root->left, target, k, q);
q.push({abs(root->val - target), root->val});
if (q.size() > k) q.pop();
inorder(root->right, target, k, q);
}
};
下面的这种方法用了两个栈,pre 和 suc,其中 pre 存小于目标值的数,suc 存大于目标值的数,开始初始化 pre 和 suc 的时候,要分别将最接近目标值的稍小值和稍大值压入 pre 和 suc,然后循环k次,每次比较 pre 和 suc 的栈顶元素,看谁更接近目标值,将其存入结果 res 中,然后更新取出元素的栈,依次类推直至取完k个数返回即可,参见代码如下:
解法五:
class Solution {
public:
vector<int> closestKValues(TreeNode* root, double target, int k) {
vector<int> res;
stack<TreeNode*> pre, suc;
while (root) {
if (root->val <= target) {
pre.push(root);
root = root->right;
} else {
suc.push(root);
root = root->left;
}
}
while (k-- > ) {
if (suc.empty() || !pre.empty() && target - pre.top()->val < suc.top()->val - target) {
res.push_back(pre.top()->val);
getPredecessor(pre);
} else {
res.push_back(suc.top()->val);
getSuccessor(suc);
}
}
return res;
}
void getPredecessor(stack<TreeNode*> &pre) {
TreeNode *t = pre.top(); pre.pop();
if (t->left) {
pre.push(t->left);
while (pre.top()->right) pre.push(pre.top()->right);
}
}
void getSuccessor(stack<TreeNode*> &suc) {
TreeNode *t = suc.top(); suc.pop();
if (t->right) {
suc.push(t->right);
while (suc.top()->left) suc.push(suc.top()->left);
}
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/272
类似题目:
Closest Binary Search Tree Value
参考资料:
https://leetcode.com/problems/closest-binary-search-tree-value-ii/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 272. Closest Binary Search Tree Value II 最近的二分搜索树的值之二的更多相关文章
- [LeetCode] Closest Binary Search Tree Value II 最近的二分搜索树的值之二
Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...
- [LeetCode] 272. Closest Binary Search Tree Value II 最近的二叉搜索树的值 II
Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...
- [LeetCode#272] Closest Binary Search Tree Value II
Problem: Given a non-empty binary search tree and a target value, find k values in the BST that are ...
- [leetcode]272. Closest Binary Search Tree Value II二叉搜索树中最近的值2
Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...
- 272. Closest Binary Search Tree Value II
题目: Given a non-empty binary search tree and a target value, find k values in the BST that are close ...
- LC 272. Closest Binary Search Tree Value II 【lock,hard】
Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...
- [Locked] Closest Binary Search Tree Value & Closest Binary Search Tree Value II
Closest Binary Search Tree Value Given a non-empty binary search tree and a target value, find the ...
- LeetCode Closest Binary Search Tree Value II
原题链接在这里:https://leetcode.com/problems/closest-binary-search-tree-value-ii/ 题目: Given a non-empty bin ...
- [Swift]LeetCode272. 最近的二分搜索树的值 II $ Closest Binary Search Tree Value II
Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...
随机推荐
- 查看xml源码的方法
查看xml源码的方法 要通过查看源码才能看到xml源码 因为 print_r输出的时候 默认页面打开是html编码的...... 所以解析不了xml
- redis之主从同步
很多企业都没有使用到 Redis 的集群,但是至少都做了主从.有了主从,当 master 挂掉的时候,运维让从库过来接管,服务就可以继续,否则 master 需要经过数据恢复和重启的过程,这就可能会拖 ...
- 一个简单的利用 WebClient 异步下载的示例(四)
接上一篇,我们继续优化它. 1. DownloadEntry 类 public class DownloadEntry { public string Url { get; set; } public ...
- Java生鲜电商平台-redis缓存在商品中的设计与架构
Java生鲜电商平台-redis缓存在商品中的设计与架构 说明:Java开源生鲜电商平台-redis缓存在商品中的设计与架构. 1. 各种计数,商品维度计数和用户维度计数 说起电商,肯定离不开商品,而 ...
- GitBash上传项目出现[fatal: remote origin already exists.]问题解决方案
问题截图如下: 当出现这个问题时,不要慌,只需要输入 git remote rm origin 就可以解决,输入完前面的命令后再次 输入 git remote add origin https://. ...
- 续~ES6 新语法 (symbol、set集合、 数组对象的filter(),reduce(),weakset(),map()方法)
一.symbol 回顾数据类型: 基本类型(原始类型): String Number Boolean Undifined Null Symbol 引用类型: Objects 1.1 创建symbol ...
- PHP 简单面向对象 验证码类(静态实例对象调用)
没事写了一个简单的面向对象验证码类,可以直接使用(替换一下字体路径) <?php class authCode { private static $instance = null; #实例对象 ...
- UILabel的各种属性和方法
转自:http://liulu200888an.blog.163.com/blog/static/3498972320121214208542/ UILabel *label1 = [[UILabe ...
- 汇编之JCC指令
版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明.2019-09-06,21:59:16.作者By-----溺心与沉浮----博客园 JCC指令决定它跳不跳转跟别的没关系,只跟EFLAG标 ...
- jenkins使用小技巧:jenkins构建出来的war/jar包如何带上SVN号?
在实际使用过程中,一般会这样比如说打出来的包是 mypackage.jar, 但是每次打出来都是固定的 mypackage.jar如何来区分和上一个包的区别呢? 一般来说,会把打出来的包带上个 svn ...