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] 272. Closest Binary Search Tree Value II 最近的二分搜索树的值之二的更多相关文章

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

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

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

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

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

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

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

  8. LeetCode Closest Binary Search Tree Value II

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

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

随机推荐

  1. centos7 更换为aliyun的yum源

    rm -f /etc/yum.repos.d/* wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Ce ...

  2. kali渗透综合靶机(十四)--g0rmint靶机

    kali渗透综合靶机(十四)--g0rmint靶机 靶机下载地址:https://www.vulnhub.com/entry/g0rmint-1,214/ 一.主机发现 1.netdiscover - ...

  3. JDBC解耦案例

    原始JDBC连接 package jdbc; import org.junit.jupiter.api.Test; import java.sql.Connection; import java.sq ...

  4. js函数定义及一些说明

    1.javascript定义函数的三种方法一.function语句//这个方法比较常用function fn(){ alert("这是使用function语句进行函数定义");}f ...

  5. Python - 字符串 - 第七天

    Python 字符串 字符串是 Python 中最常用的数据类型.我们可以使用引号( ' 或 " )来创建字符串. 创建字符串很简单,只要为变量分配一个值即可.例如: var1 = 'Hel ...

  6. SQL server已经设置为单用户模式,Sql server还原失败数据库正在使用,无法获得对数据库的独占访问权

    如果已经设置为单用户模式,还是报这个错误的话,就按照一下SQL执行就

  7. 剑指 Offer——1. 二维数组中的查找

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  8. maven 学习---Maven依赖管理

    其中一个Maven的核心特征是依赖管理.管理依赖关系变得困难的任务一旦我们处理多模块项目(包含数百个模块/子项目). Maven提供了一个高程度的控制来管理这样的场景. 传递依赖发现 这是很通常情况下 ...

  9. 【已解决】git的一些常用命令

    git:分布式的版本管理系统,一般的开发模式: 如果是开发人员,忽略此步骤,从下面大字的开始即可: 项目开始阶段,初始化项目(init),提交本地的代码到仓库,将本地仓库的代码推送到远端库(push) ...

  10. 利用javascript动态加载头部出现点击事件与hover事件无效解决方法

    这里是利用es6的promise函数来异步加载,当HTML动态加载过去的HTML片段加载完毕再执行绑定事件的js代码: 具体过程如下 这里是用了jQuery框架的例子 $(function(){ // ...