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

Binary Tree Inorder Traversal

参考资料:

https://leetcode.com/problems/closest-binary-search-tree-value-ii/

https://leetcode.com/problems/closest-binary-search-tree-value-ii/discuss/70515/Java-in-order-traversal-1ms-solution

https://leetcode.com/problems/closest-binary-search-tree-value-ii/discuss/70511/AC-clean-Java-solution-using-two-stacks

https://leetcode.com/problems/closest-binary-search-tree-value-ii/discuss/70549/Clear-Java-Solution-with-one-stack-one-linkedlist

https://leetcode.com/problems/closest-binary-search-tree-value-ii/discuss/70503/O(logN)-Java-Solution-with-two-stacks-following-hint

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Closest Binary Search Tree Value II 最近的二分搜索树的值之二的更多相关文章

  1. [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 t ...

  2. LeetCode Closest Binary Search Tree Value II

    原题链接在这里:https://leetcode.com/problems/closest-binary-search-tree-value-ii/ 题目: Given a non-empty bin ...

  3. [LeetCode] Closest Binary Search Tree Value 最近的二分搜索树的值

    Given a non-empty binary search tree and a target value, find the value in the BST that is closest t ...

  4. LeetCode Closest Binary Search Tree Value

    原题链接在这里:https://leetcode.com/problems/closest-binary-search-tree-value/ Given a non-empty binary sea ...

  5. [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 ...

  6. [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 ...

  7. 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 ...

  8. [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 ...

  9. [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 ...

随机推荐

  1. Vertica 分区表设计(续)

    在上篇Vertica 分区表设计中,已经提过了Vertica的分区表创建和分区删除,但举例上并不系统, 本篇文章将系统的对分区表设计及后续的删除分区进行讲解. 概述:Vertica分区表(天和月)创建 ...

  2. Javascript学习笔记1

    一.写在前面的话 之前一直没有系统的学习javascript,自己也是小白,很多东西感觉不会,从本篇起,自己会抽出时间来,慢慢学习,好好领会! 深知学习是一个漫长的过程,来不得急躁,不积跬步,无以至千 ...

  3. MyCat源码分析系列之——BufferPool与缓存机制

    更多MyCat源码分析,请戳MyCat源码分析系列 BufferPool MyCat的缓冲区采用的是java.nio.ByteBuffer,由BufferPool类统一管理,相关的设置在SystemC ...

  4. asp.net core 依赖注入问题

    最近.net core可以跨平台了,这是一个伟大的事情,为了可以赶上两年以后的跨平台部署大潮,我也加入到了学习之列.今天研究的是依赖注入,但是我发现一个问题,困扰我很久,现在我贴出来,希望可以有人帮忙 ...

  5. 『.NET Core CLI工具文档』(十三)dotnet-publish

    说明:本文是个人翻译文章,由于个人水平有限,有不对的地方请大家帮忙更正. 原文:dotnet-publish 翻译:dotnet-publish 名称 dotnet-publish - 打包应用程序及 ...

  6. .Net语言 APP开发平台——Smobiler学习日志:如何快速实现快递信息流的效果

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 样式一 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的&qu ...

  7. ASP.NET MVC 利用IRouteHandler, IHttpHandler实现图片防盗链

    你曾经注意过在你服务器请求日志中多了很多对图片资源的请求吗?这可能是有人在他们的网站中盗链了你的图片所致,这会占用你的服务器带宽.下面这种方法可以告诉你如何在ASP.NET MVC中实现一个自定义Ro ...

  8. C#——this关键字(1)

    //我的C#是跟着猛哥(刘铁猛)(算是我的正式老师)<C#语言入门详解>学习的,微信上猛哥也给我讲解了一些不懂得地方,对于我来说简直是一笔巨额财富,难得良师! 在学习C#的时候,老师讲的示 ...

  9. WebService 概念和工作原理(一)

    今天我们一起来学习WebService.它到底是干啥用的? Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集) ...

  10. 如何在webapp中做出原生的ios下拉菜单效果

    github:https://github.com/zhoushengmufc/iosselect webapp模仿ios下拉菜单 html下拉菜单select在安卓和IOS下表现不一样,iossel ...