- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在研究如何在 BST 中找到最接近目标的 k 个值,并遇到了以下使用规则的实现:
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. Assume that the BST is balanced.
实现的思路是:
Compare the predecessors and successors of the closest node to the target, we can use two stacks to track the predecessors and successors, then like what we do in merge sort, we compare and pick the closest one to the target and put it to the result list. As we know, inorder traversal gives us sorted predecessors, whereas reverse-inorder traversal gives us sorted successors.
代码:
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) {
val = x;
}
}
public class ClosestBSTValueII {
List<Integer> closestKValues(TreeNode root, double target, int k) {
List<Integer> res = new ArrayList<>();
Stack<Integer> s1 = new Stack<>(); // predecessors
Stack<Integer> s2 = new Stack<>(); // successors
inorder(root, target, false, s1);
inorder(root, target, true, s2);
while (k-- > 0) {
if (s1.isEmpty()) {
res.add(s2.pop());
} else if (s2.isEmpty()) {
res.add(s1.pop());
} else if (Math.abs(s1.peek() - target) < Math.abs(s2.peek() - target)) {
res.add(s1.pop());
} else {
res.add(s2.pop());
}
}
return res;
}
// inorder traversal
void inorder(TreeNode root, double target, boolean reverse, Stack<Integer> stack) {
if (root == null) {
return;
}
inorder(reverse ? root.right : root.left, target, reverse, stack);
// early terminate, no need to traverse the whole tree
if ((reverse && root.val <= target) || (!reverse && root.val > target)) {
return;
}
// track the value of current node
stack.push(root.val);
inorder(reverse ? root.left : root.right, target, reverse, stack);
}
public static void main(String args[]) {
ClosestBSTValueII cv = new ClosestBSTValueII();
TreeNode root = new TreeNode(53);
root.left = new TreeNode(30);
root.left.left = new TreeNode(20);
root.left.right = new TreeNode(42);
root.right = new TreeNode(90);
root.right.right = new TreeNode(100);
System.out.println(cv.closestKValues(root, 40, 2));
}
}
我的问题是,有两个堆栈的原因是什么?有序是一种好的方法吗?每个的目的是什么?用一个堆栈遍历它还不够吗?
reverse
有什么意义呢? boolean 值,例如 inorder(reverse ? ...);
?在 if ((reverse && root.val <= target) || (!reverse && root.val > target))
的情况下,你为什么提前终止?
在此先感谢您,并将接受回答/赞成票。
最佳答案
您找到的算法的思想非常简单。他们只是从target
的地方按顺序遍历一棵树。应该插入。他们使用两个栈来存储前驱和后继。让我们以树为例:
5
/ \
3 9
/ \ \
2 4 11
设目标为8
.当所有inorder
方法调用完成后,堆栈将是:s1 = {2, 3, 4, 5}
, s2 = {11, 9}
.如您所见,s1
包含 target
的所有前身和 s2
它的所有继承者。此外,两个堆栈都以某种方式排序,即 top
每个堆栈的更接近 target
,比堆栈中的所有其他值。结果,我们很容易找到k
最接近的值,只需始终比较堆栈的顶部,并弹出最接近的值,直到我们有 k
值。他们算法的运行时间是O(n)
.
现在谈谈你的问题。我不知道,如何使用唯一的堆栈有效地实现这个算法。堆栈的问题是我们只能访问它的顶部。但是用一个数组来实现这个算法是非常容易的。让我们按常规顺序遍历一棵树。对于我的示例,我们将得到:arr = {2, 3, 4, 5, 9, 11}
.然后让我们放置l
和 r
两侧最接近目标值的索引:l = 3
, r = 4
( arr[l] = 5
, arr[r] = 9
)。剩下的就是一直比较arr[l]
和 arr[r]
并选择要添加到结果中的内容(绝对相同,与两个堆栈一样)。该算法还采用 O(n)
操作。
他们解决问题的方法在我看来有点难以用代码理解,尽管它相当优雅。
我想介绍另一种方法来解决另一个运行时的问题。该算法将采用 O(k*logn)
时间,哪个对小比较好k
对于比以前的算法更大的算法更糟。
我们也存储在 TreeNode
中类指向父节点的指针。然后我们可以很容易地在 O(logn)
中找到树中任何节点的前驱或后继。时间(if you don't know how)。因此,让我们首先在树中找到目标的前驱和后继(不进行任何遍历!)。然后做与堆栈相同的事情:比较前驱\后继,选择最接近的,最接近它的前驱\后继。
我希望,我回答了您的问题并且您理解了我的解释。如果没有,请随时询问!
关于Java:如何在 BST 中找到最接近目标的 k 个值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41095912/
我已经编写了一个 BSTLink 类来将 BST 转换为双向链表,但是在我尝试通过引用传递 BST 的节点指针的类中的构造调用抛出一个错误“没有匹配的函数来调用 BSTLink::construct(
当我使用 xgboost 为 2-cates classification problem 训练我的数据时,我想使用提前停止来获得最佳模型,但我对在我的预测中使用哪一个感到困惑,因为提前停止将返回 3
因为我找不到有用的东西所以我在这里问我的问题: 我们如何在不使用任何额外空间的情况下将 BST 转换为中序链接列表,然后再转换回“相同”的 BST。 到目前为止我已经尝试过的(虽然仍在做):我尝试了
我从我们的教授讲座幻灯片中获得了 BST(二叉搜索树)和随机 BST 的源代码,现在我想通过插入新元素来测试它们是否正常工作,然后我如何才能看到我的结果,如 http://cs.lmu.edu/~ra
给定两棵二叉树 T1 和 T2,您必须找到要在 T1 中完成的最少插入次数,以使其在结构上与 T2 相同。如果不可能则返回 -1。 注意事项 假设插入在 BST 中以正常方式完成。 假设在插入时,如果
我有一个始终将日期存储为 UTC 的网络应用程序,但它们需要分别以 GMT/BST 的形式显示给用户。 我有一个 UTC/GMT 日期(2013 年 3 月 30 日 22:00),我每小时移动一次以
题目地址:https://leetcode-cn.com/problems/largest-bst-subtree/ 题目描述 Given a binary tree, find the larg
注意:BST - 二叉搜索树(缩写) 正如标题所说,这是一项家庭作业,所以我不是在寻找答案。相反,我只需要一个正确方向的点。 对于作业,我应该创建一个 BST 类,它直接定义为最多包含 2 个 BST
我有一个插入方法和一个搜索方法,我正在考虑一种方法来循环二叉搜索树并使用像获取节点这样的方法,然后在另一个二叉搜索树上搜索它,如果它成立,那么我将其插入该元素,但问题是我无法想出一种基于索引获取节点的
二叉查找树 (Binary Search Tree, 简称 BST) 是一种基本的数据结构,其设计核心在于每个节点的值都满足以下性质: 左子树的所有节点值均小于当前节点值。 右子树的所有节
function validateBst(root, min=-Infinity, max=Infinity) { if (!root) return true; if (root.value
我有一个问题,我知道如何像这样计算树中的所有节点 return 1 + rightchild(tree->right) + rightchild(tree->left); 现在我的问题是如果一个节点在
给定一个二叉树根,任务是返回 任何子树的所有键的最大总和 这也是 二叉搜索树 (BST) . 假设 BST 定义如下: - 节点的左子树仅包含键小于节点键的节点。 - 节点的右子树仅包含键大于节点键的
我正在尝试使用 ScalaCheck 为 BST 创建一个 Gen,但是当我调用 .sample 方法时,它给了我 java.lang.NullPointerException。我哪里错了? seal
这些是我的领域: public class BSTSet extends AbstractSet { // Data fields private BSTNode root;
我需要在二叉搜索树中执行范围搜索功能,这将给出给定范围内的项目数量。我不明白如何在找到项目时增加计数值。因为,我必须使用递归函数&如果我在递归过程中将计数变量初始化为0,它将始终从0开始计数值,而不是
所以我正在尝试编写一个代码来返回二叉搜索树中的最小值。我知道这是树的最左边的值,并且我知道我需要它递归地向左运行,直到什么都没有为止。但是我的代码不起作用,我不知道为什么。任何帮助将不胜感激。 (de
我想返回一个包含树中所有键的字符串,按照它们的存储顺序。每个子树中的键应包含在括号中。 _7_ / \ _3_ 8 / \ 1
尝试运行递归算法来找出某棵树是否是 BST(二叉搜索树)。 boolean checkBST(Node root) { boolean isBST = true; if(root ==
使用下面的代码,每个时区都正确打印值,除了 BST import java.text.*; def format = "yyyy-MM-dd HH:mm:ssXXX" def dt = new Da
我是一名优秀的程序员,十分优秀!