news 2026/5/30 19:34:36

算法题 二叉搜索树的范围和

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题 二叉搜索树的范围和

938. 二叉搜索树的范围和

问题描述

给定二叉搜索树的根节点root,以及两个整数lowhigh,返回所有节点值在范围[low, high]内的节点值之和。

二叉搜索树

  • 对于任意节点,左子树的所有节点值都小于该节点值
  • 右子树的所有节点值都大于该节点值
  • 左右子树也都是二叉搜索树

示例

输入: root = [10,5,15,3,7,null,18], low = 7, high = 15 输出: 32 解释: 节点值在[7,15]范围内的有: 7, 10, 15,和为32。 输入: root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10 输出: 23 解释: 节点值在[6,10]范围内的有: 6, 7, 10,和为23。

算法思路

核心思想

  • 如果当前节点值小于low,则左子树所有节点都不在范围内,只需遍历右子树
  • 如果当前节点值大于high,则右子树所有节点都不在范围内,只需遍历左子树
  • 如果当前节点值在范围内,则累加该节点值,并递归遍历左右子树

代码实现

方法一:递归

/** * 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; * } * } */classSolution{/** * 计算二叉搜索树中范围[low, high]内节点值的和 * * @param root 二叉搜索树的根节点 * @param low 范围下界(包含) * @param high 范围上界(包含) * @return 范围内节点值的和 */publicintrangeSumBST(TreeNoderoot,intlow,inthigh){// 基础情况:空节点if(root==null){return0;}// 当前节点值小于low,左子树都不在范围内,只遍历右子树if(root.val<low){returnrangeSumBST(root.right,low,high);}// 当前节点值大于high,右子树都不在范围内,只遍历左子树if(root.val>high){returnrangeSumBST(root.left,low,high);}// 当前节点值在范围内,累加当前值 + 左右子树的结果returnroot.val+rangeSumBST(root.left,low,high)+rangeSumBST(root.right,low,high);}}

方法二:迭代

classSolution{/** * 使用显式栈避免递归 */publicintrangeSumBST(TreeNoderoot,intlow,inthigh){if(root==null){return0;}Stack<TreeNode>stack=newStack<>();stack.push(root);intsum=0;while(!stack.isEmpty()){TreeNodecurrent=stack.pop();if(current==null){continue;}// 当前节点值在范围内if(current.val>=low&&current.val<=high){sum+=current.val;// 左右子树都可能有符合条件的节点stack.push(current.left);stack.push(current.right);}// 当前节点值小于low,只考虑右子树elseif(current.val<low){stack.push(current.right);}// 当前节点值大于high,只考虑左子树else{stack.push(current.left);}}returnsum;}}

方法三:BFS层序遍历

classSolution{/** * 使用队列进行层序遍历 */publicintrangeSumBST(TreeNoderoot,intlow,inthigh){if(root==null){return0;}Queue<TreeNode>queue=newLinkedList<>();queue.offer(root);intsum=0;while(!queue.isEmpty()){TreeNodecurrent=queue.poll();if(current.val>=low&&current.val<=high){sum+=current.val;if(current.left!=null)queue.offer(current.left);if(current.right!=null)queue.offer(current.right);}elseif(current.val<low){if(current.right!=null)queue.offer(current.right);}else{// current.val > highif(current.left!=null)queue.offer(current.left);}}returnsum;}}

方法四:无剪枝的递归

classSolution{/** * 简单递归 */publicintrangeSumBST(TreeNoderoot,intlow,inthigh){if(root==null){return0;}intsum=0;if(root.val>=low&&root.val<=high){sum+=root.val;}// 无论当前值如何,都要遍历左右子树sum+=rangeSumBST(root.left,low,high);sum+=rangeSumBST(root.right,low,high);returnsum;}}

算法分析

方法时间复杂度空间复杂度
递归O(n) 最坏, O(log n) 平均O(h)
迭代O(n) 最坏, O(log n) 平均O(h)
BFSO(n) 最坏, O(log n) 平均O(w)
无剪枝递归O(n)O(h)

算法过程

输入:root = [10,5,15,3,7,null,18], low = 7, high = 15

  1. root.val = 10∈ [7,15] → 累加10,递归左右子树
  2. 左子树(5)5 < 7→ 只遍历右子树(7)
    • 7 ∈ [7,15]→ 累加7,左右子树为空
  3. 右子树(15)15 ∈ [7,15]→ 累加15,递归左右子树
    • 左子树为空
    • 右子树(18):18 > 15→ 只遍历左子树(为空)
  4. 总和 = 10 + 7 + 15 = 32

输入:root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10

  1. 10 ∈ [6,10]→ 累加10
  2. 左子树(5)5 < 6→ 只遍历右子树(7)
    • 7 ∈ [6,10]→ 累加7
    • 左子树(6):6 ∈ [6,10]→ 累加6
  3. 右子树(15)15 > 10→ 只遍历左子树(13)
    • 13 > 10→ 只遍历左子树(为空)
  4. 总和 = 10 + 7 + 6 = 23

测试用例

publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 创建树节点TreeNodecreateNode(intval){returnnewTreeNode(val);}// 测试用例1:标准示例TreeNoderoot1=newTreeNode(10);root1.left=newTreeNode(5);root1.right=newTreeNode(15);root1.left.left=newTreeNode(3);root1.left.right=newTreeNode(7);root1.right.right=newTreeNode(18);System.out.println("Test 1: "+solution.rangeSumBST(root1,7,15));// 32// 测试用例2:另一个标准示例TreeNoderoot2=newTreeNode(10);root2.left=newTreeNode(5);root2.right=newTreeNode(15);root2.left.left=newTreeNode(3);root2.left.right=newTreeNode(7);root2.right.left=newTreeNode(13);root2.right.right=newTreeNode(18);root2.left.left.left=newTreeNode(1);root2.left.right.left=newTreeNode(6);System.out.println("Test 2: "+solution.rangeSumBST(root2,6,10));// 23// 测试用例3:空树System.out.println("Test 3: "+solution.rangeSumBST(null,1,10));// 0// 测试用例4:单节点在范围内TreeNoderoot4=newTreeNode(5);System.out.println("Test 4: "+solution.rangeSumBST(root4,5,5));// 5// 测试用例5:单节点不在范围内System.out.println("Test 5: "+solution.rangeSumBST(root4,6,10));// 0// 测试用例6:所有节点都在范围内TreeNoderoot6=newTreeNode(5);root6.left=newTreeNode(3);root6.right=newTreeNode(7);System.out.println("Test 6: "+solution.rangeSumBST(root6,1,10));// 15// 测试用例7:所有节点都不在范围内System.out.println("Test 7: "+solution.rangeSumBST(root6,8,10));// 0// 测试用例8:边界值TreeNoderoot8=newTreeNode(10);root8.left=newTreeNode(5);root8.right=newTreeNode(15);System.out.println("Test 8: "+solution.rangeSumBST(root8,10,10));// 10System.out.println("Test 9: "+solution.rangeSumBST(root8,5,15));// 30// 测试用例9:大范围System.out.println("Test 10: "+solution.rangeSumBST(root8,1,100));// 30}

关键点

  1. 边界处理
    • 空树返回0
    • 单节点
    • 范围边界值

常见问题

  1. 为什么不用中序遍历?
    • 中序遍历虽然能得到有序序列,但无法利用范围信息进行剪枝
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/24 18:05:41

SGMICRO圣邦微 SGM2203-12YK3G/TR SO89-3 线性稳压器(LDO)

特性高输入电压&#xff1a;最高36V固定输出电压&#xff1a;2.5V、2.8V、3.0V、3.3V、3.5V、3.6V、4.0V、4.2V、5.0V、5.75V、8.0V、9.0V和12V150mA输出电流输出电压精度&#xff1a;25C时为3%低压差电压低功耗&#xff1a;4.2μA&#xff08;典型值&#xff09;低温漂系数限流…

作者头像 李华
网站建设 2026/5/20 20:45:09

计算机毕业设计|基于springboot + vue校园外卖系统(源码+数据库+文档)

校园外卖 目录 基于springboot vue校园外卖系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue校园外卖系统 一、前言 博主介绍&#xff1a;✌️大…

作者头像 李华
网站建设 2026/5/29 12:24:39

AI赋能盾构隧道巡检开启基建安全新篇章,基于最新端到端范式YOLO26全系列【n/s/m/l】参数模型开发构建AI隧道盾构场景下盾构管壁缺陷病害异常检测预警系统

在当今交通网络日益发达的时代&#xff0c;涵洞隧道作为交通基础设施的关键组成部分&#xff0c;其重要性不言而喻。它们宛如城市脉络中的隐秘通道&#xff0c;保障着车辆与行人的顺畅通行。而在隧道等基建施工建设过程中&#xff0c;工程质量监管是重中之重&#xff0c;直接关…

作者头像 李华