Java 使用DFS的BST范围和
问题:给定二叉搜索树的根节点,返回值介于L和R(包括L和R)之间的所有节点的值之和 二叉搜索树保证具有唯一的值 例1: 输入:root=[10,5,15,3,7,null,18],L=7,R=15 产出:32 Leetcode问题: 我的方法:我正在尝试执行dfs并访问每个节点,如果该节点上的值符合约束条件,那么我希望在递归函数中返回它。然后,我将所有值相加,并将其返回到我的主函数 我仍在试图理解递归,我在这段代码中做错了什么(为什么它只返回10而不是32?) 我试图从每个递归函数返回一个值,并在最后添加它-这样做有意义吗Java 使用DFS的BST范围和,java,recursion,tree,binary-tree,depth-first-search,Java,Recursion,Tree,Binary Tree,Depth First Search,问题:给定二叉搜索树的根节点,返回值介于L和R(包括L和R)之间的所有节点的值之和 二叉搜索树保证具有唯一的值 例1: 输入:root=[10,5,15,3,7,null,18],L=7,R=15 产出:32 Leetcode问题: 我的方法:我正在尝试执行dfs并访问每个节点,如果该节点上的值符合约束条件,那么我希望在递归函数中返回它。然后,我将所有值相加,并将其返回到我的主函数 我仍在试图理解递归,我在这段代码中做错了什么(为什么它只返回10而不是32?) 我试图从每个递归函数返回一个值,并
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int rangeSumBST(TreeNode root, int L, int R) {
if(root == null) {
return 0;
}
rangeBST(root, L, R);
return rangeBST(root, L, R);
}
public static int rangeBST(TreeNode root, int L, int R) {
if(root == null) {
return 0;
}
if(root.val >= L && root.val <= R) {
return root.val;
}
int x = rangeBST(root.left, L, R);
int y = rangeBST(root.right, L, R);
return x + y;
}
}
/**
*二叉树节点的定义。
*公共级树节点{
*int-val;
*左树突;
*特雷诺德右翼;
*TreeNode(){}
*树节点(int-val){this.val=val;}
*TreeNode(内部值,TreeNode左,TreeNode右){
*this.val=val;
*this.left=左;
*这个。右=右;
* }
* }
*/
类解决方案{
公共内部范围(树根、内部L、内部R){
if(root==null){
返回0;
}
rangeBST(根,L,R);
返回范围BST(根、L、R);
}
公共静态整数范围BST(树节点根、整数L、整数R){
if(root==null){
返回0;
}
如果(root.val>=L&&root.val您在末尾添加这些值并使用返回值的方法是正确的。(在使用指针算术或通过引用变量传递的语言中,您可以传递对整数的引用并增加接收值,而不必返回值。)
但在使用“returnroot.val”时,您遇到了一个问题
public int rangeSumBST(TreeNode root, int l, int r) {
if(root == null)
return 0;
// This is a problem because you are stopping with your recursive search
// if one value was found. This is the reason because it is returning 10 in your example
// if(root.val >= L && root.val <= R) return root.val;
int result = 0;
// So your looking at your node, if the value is in the range you want.
if (root.val >= l && root.val <= r)
result += root.val;
// Add the ranged summ of your left node
result += rangeSumBST(root.left, l, r);
// Add the ranged summ of your right node
result += rangeSumBST(root.right, l, r);
// And your done
return result;
}
public int rangeSumBST(树节点根,int l,int r){
if(root==null)
返回0;
//这是一个问题,因为您正在停止递归搜索
//如果找到一个值,这就是原因,因为在您的示例中它返回10
//如果(root.val>=L&&root.val=L&&root.val两个问题:
- 当值在L-R范围之间时,该算法应更深入地重现,但返回当前节点自己的值时,不会再深入查看
- 算法不应该总是需要访问每个节点,而是利用BST属性:当当前值不排除时,它应该只在左子树中搜索,以在该子树中找到任何范围内的值
例如,如果当前节点的值为3,且L-R范围为(5,9),则进一步查看左子树是没有意义的,因为在左子树中,所有值都保证小于3,无论该子树有多大
右子树也有类似的观察结果
类解决方案{
公共内部范围(树根、内部L、内部R){
if(root==null)返回0;
int-val=0;
如果(root.val>=L&&root.val L)val+=rangeSumBST(root.left,L,R);
返回val;
}
}
我完全同意您的第一个问题,但我认为第二个问题不是真正的问题,因为您的运行时复杂性仍然是O(N)(它没有改变)但是你必须进一步增加圈复杂度,以改善二进制树的随机情况下的中间运行时间。如果证明这个函数是一个瓶颈,这是唯一应该做的。我不认为时间复杂度改变了,但是我认为这仍然是个问题,因为最佳情况的时间复杂度从O(n)提高到O(1)。,这会对站点上的运行时间产生相当大的影响,在这些站点上,运行时间会被测量并得到比较分数(如:Leetcode)运行到TLE的解决方案。因此,不仅时间复杂度很重要,绝对运行时间也很重要。是的,它会对绝对运行时间产生重大影响。但是,如果不是绝对有必要优化运行时间,我不会添加进一步的逻辑,因为可能存在更多的变异、错误源和可维护性问题。这是你的自由选择。我更喜欢利用给定的信息,这涉及到一个BST,而不仅仅是一个二叉树。附加的if
条件是BST的典型条件,因此预计在所有涉及BST导航的代码中都会有这样的逻辑。
class Solution {
public int rangeSumBST(TreeNode root, int L, int R) {
if (root == null) return 0;
int val = 0;
if (root.val >= L && root.val <= R) val += root.val;
if (root.val < R) val += rangeSumBST(root.right, L, R);
if (root.val > L) val += rangeSumBST(root.left, L, R);
return val;
}
}