[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 ...
随机推荐
- SqlBulkCopy将DataTable中的数据批量插入数据库中
#region 使用SqlBulkCopy将DataTable中的数据批量插入数据库中 /// <summary> /// 注意:DataTable中的列需要与数据库表中的列完全一致.// ...
- 一个动态构建 LambdaExpression Tree 的示例
直接贴代码了: public class ExpressionTreeBuildingSampleTwo : Sample { public override string Name { get; } ...
- 云原生生态周报 Vol.9| K8s v1.15 版本发布
本周作者 | 衷源.心贵 业界要闻 1.Kubernetes Release v1.15 版本发布,新版本的两个主题是持续性改进和可扩展性.(https://github.com/kubernetes ...
- RESTful服务最佳实践(转)
原文:https://www.cnblogs.com/jaxu/p/7908111.html 译文作者:Jaxu 英文原文:https://files-cdn.cnblogs.com/files/ja ...
- mongodb 更新数据时int32变为double的解决办法 & 教程
https://www.runoob.com/mongodb/mongodb-mongodump-mongorestore.html mongodb 更新数据时int32变为double的解决办法 ...
- asp.net mvc4 bundle添加带min的js问题
今天在用ScriptBundle的时候发现js文件有min的,无法bundle进去,具体我也不知道怎么回事. @Tony Tan 回复:bundles.IgnoreList可以设置 去除min.js的 ...
- 剑指 Offer——1. 二维数组中的查找
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- 2019 北森java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.北森等公司offer,岗位是Java后端开发,因为发展原因最终选择去了北森,入职一年时间了,也成为了面试官,之 ...
- Ajax异步后台加载Html绑定不上事件
因项目需要,需要实时从后台动态加载html,开发过程中,遇到事件绑定不上,后来百度一番,大概意思:ajax是异步加载的,页面一开始绑定事件的时候,后台数据还没有传过来,就绑定事件,这个时候找不到这个d ...
- Vue实战狗尾草博客管理系统第一章
Vue实战狗尾草博客后台管理系统第一章 这里准备采用的技术栈为:vue全家桶+element-ui 这里因为是后台管理系统,没有做SSR的必要.所以这里就采用前后端分离来昨晚这个项目~ 项目搭建 vu ...