这是我参与更文挑战的第5天,活动详情查看: 更文挑战
二叉搜索树的范围和(题号938)
题目
给定二叉搜索树的根结点 root
,返回值位于范围[low, high]
之间的所有结点的值的和。
示例 1:
输入:root = [10,5,15,3,7,null,18], low = 7, high = 15
输出:32
示例 2:
输入:root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10
输出:23
提示:
- 树中节点数目在范围
[1, 2 * 104]
内 1 <= Node.val <= 105
1 <= low <= high <= 105
- 所有
Node.val
互不相同
链接
解释
这题啊,这题其实就是剪枝,只要把剪枝条件写好了,剩下的其实非常简单。
首先看题目,这是一个二叉搜索树,那么就不用找到所有节点了。一个节点左子树的值必然比当前节点的值小,右子树的值必然比当前节点的值大。
这样剪枝条件就很明显了,如果当前节点的值小于最小值,那么其左子树的值就不用考虑了;同理可得如果当前节点的值比最大值大,那么其右子树的值就不用考虑了。
就是这么简单,那么接下来看看递归和迭代两种写法。
自己的答案(迭代)
var rangeSumBST = function(root, low, high) {
var res = 0
stack = [root]
while (stack.length) {
root = stack.pop()
if (root.val < low) {
root.right && stack.push(root.right)
continue
}
if (root.val > high) {
root.left && stack.push(root.left)
continue
}
root.left && stack.push(root.left)
root.right && stack.push(root.right)
res += root.val
}
return res
};
非常简单,如果当前节点的值小于最小值,那么只将其右子树推入到栈中,并且结束此次迭代;同理可以得到大于最大值时的处理方式。如果没有走到两个if
中去,那就证明这个节点的值在最大值和最小值中间,将左右子树都推入栈并且累计res
即可。
自己的答案(递归)
递归也是很简单,这里为了方便就不新建一个递归函数了,直接调用原函数。
var rangeSumBST = function(root, low, high) {
if (!root) return 0
if (root.val < low) return rangeSumBST(root.right, low, high)
if (root.val > high) return rangeSumBST(root.left, low, high)
return root.val + rangeSumBST(root.left, low, high) + rangeSumBST(root.right, low, high)
};
首先是递归的终止条件,当节点为null
时结束递归,因为此时已经递归到头了。
之后如果当前节点值小于最小值,返回右子树的递归结果,如果当前节点大于最大值,返回左子树的递归结果。
如果当前节点在最大值和最小值之间,那么就返回左右递归结果的和加上当前节点值。
相比迭代来说,递归的代码好像更简单一些,不过知道两种解法总比一种好些。
更好的答案
无
PS:想查看往期文章和题目可以点击下面的链接:
这里是按照日期分类的👇
经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇
有兴趣的也可以看看我的个人主页👇