当前位置: 首页 > ds >正文

Android学习总结之算法篇八(二叉树和数组)

路径总和

import java.util.ArrayList;
import java.util.List;// 定义二叉树节点类
class TreeNode {int val;TreeNode left;TreeNode right;// 构造函数,用于初始化节点值TreeNode(int x) {val = x;}
}public class PathSumProblems {// 路径总和 I:判断是否存在从根节点到叶子节点的路径,使得路径上所有节点值的和等于给定的目标值public boolean hasPathSumI(TreeNode root, int sum) {// 若根节点为空,不存在满足条件的路径if (root == null) {return false;}// 若当前节点为叶子节点,判断当前节点值是否等于剩余的和if (root.left == null && root.right == null) {return root.val == sum;}// 递归在左子树和右子树中查找return hasPathSumI(root.left, sum - root.val) || hasPathSumI(root.right, sum - root.val);}// 路径总和 II:找出所有从根节点到叶子节点的路径,使得路径上所有节点值的和等于给定的目标值public List<List<Integer>> pathSumII(TreeNode root, int sum) {List<List<Integer>> result = new ArrayList<>();if (root == null) {return result;}dfsII(root, sum, new ArrayList<>(), result);return result;}// 深度优先搜索辅助方法,用于路径总和 IIprivate void dfsII(TreeNode node, int remainingSum, List<Integer> currentPath, List<List<Integer>> result) {if (node == null) {return;}// 将当前节点加入路径currentPath.add(node.val);remainingSum -= node.val;// 若当前节点为叶子节点且剩余和为 0,说明找到了一条满足条件的路径if (node.left == null && node.right == null && remainingSum == 0) {result.add(new ArrayList<>(currentPath));}// 递归遍历左子树和右子树dfsII(node.left, remainingSum, currentPath, result);dfsII(node.right, remainingSum, currentPath, result);// 回溯,移除当前节点currentPath.remove(currentPath.size() - 1);}// 路径总和 III:计算二叉树中路径和等于给定值的路径总数,路径不需要从根节点开始,也不需要在叶子节点结束public int pathSumIII(TreeNode root, int sum) {if (root == null) {return 0;}// 以当前节点为起点的路径数量int pathsFromRoot = countPathsIII(root, sum);// 左子树中的路径数量int pathsInLeft = pathSumIII(root.left, sum);// 右子树中的路径数量int pathsInRight = pathSumIII(root.right, sum);return pathsFromRoot + pathsInLeft + pathsInRight;}// 辅助方法,用于计算以当前节点为起点的路径数量private int countPathsIII(TreeNode node, int remainingSum) {if (node == null) {return 0;}int paths = 0;// 若当前节点值等于剩余和,说明找到了一条路径if (node.val == remainingSum) {paths++;}// 递归在左子树和右子树中查找paths += countPathsIII(node.left, remainingSum - node.val);paths += countPathsIII(node.right, remainingSum - node.val);return paths;}public static void main(String[] args) {// 构建一个简单的二叉树TreeNode root = new TreeNode(10);root.left = new TreeNode(5);root.right = new TreeNode(-3);root.left.left = new TreeNode(3);root.left.right = new TreeNode(2);root.right.right = new TreeNode(11);root.left.left.left = new TreeNode(3);root.left.left.right = new TreeNode(-2);root.left.right.right = new TreeNode(1);PathSumProblems solution = new PathSumProblems();// 测试路径总和 Iint targetSumI = 8;boolean resultI = solution.hasPathSumI(root, targetSumI);System.out.println("路径总和 I:是否存在路径和为 " + targetSumI + " 的路径: " + resultI);// 测试路径总和 IIint targetSumII = 8;List<List<Integer>> resultII = solution.pathSumII(root, targetSumII);System.out.println("路径总和 II:路径和为 " + targetSumII + " 的所有路径: " + resultII);// 测试路径总和 IIIint targetSumIII = 8;int resultIII = solution.pathSumIII(root, targetSumIII);System.out.println("路径总和 III:路径和为 " + targetSumIII + " 的路径总数: " + resultIII);}
}    

组合总和

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class CombinationSumProblems {// 组合总和 I:找出 candidates 中所有可以使数字和为 target 的组合,candidates 中的数字可以无限制重复被选取public List<List<Integer>> combinationSumI(int[] candidates, int target) {List<List<Integer>> result = new ArrayList<>();if (candidates == null || candidates.length == 0) {return result;}// 调用回溯方法backtrackI(candidates, target, 0, new ArrayList<>(), result);return result;}private void backtrackI(int[] candidates, int remaining, int start, List<Integer> current, List<List<Integer>> result) {// 如果剩余值为 0,说明找到了一个有效的组合if (remaining == 0) {result.add(new ArrayList<>(current));return;}// 如果剩余值小于 0,说明当前组合不满足条件if (remaining < 0) {return;}// 从 start 开始遍历 candidates 数组for (int i = start; i < candidates.length; i++) {// 将当前数字加入组合current.add(candidates[i]);// 递归调用,由于数字可以重复使用,下一次递归的 start 仍然是 ibacktrackI(candidates, remaining - candidates[i], i, current, result);// 回溯,移除最后一个数字current.remove(current.size() - 1);}}// 组合总和 II:找出 candidates 中所有可以使数字和为 target 的组合,candidates 中的每个数字在每个组合中只能使用一次public List<List<Integer>> combinationSumII(int[] candidates, int target) {List<List<Integer>> result = new ArrayList<>();if (candidates == null || candidates.length == 0) {return result;}// 对数组进行排序,方便去重Arrays.sort(candidates);// 调用回溯方法backtrackII(candidates, target, 0, new ArrayList<>(), result);return result;}private void backtrackII(int[] candidates, int remaining, int start, List<Integer> current, List<List<Integer>> result) {// 如果剩余值为 0,说明找到了一个有效的组合if (remaining == 0) {result.add(new ArrayList<>(current));return;}// 如果剩余值小于 0,说明当前组合不满足条件if (remaining < 0) {return;}// 从 start 开始遍历 candidates 数组for (int i = start; i < candidates.length; i++) {// 跳过重复的数字,避免结果中出现重复组合if (i > start && candidates[i] == candidates[i - 1]) {continue;}// 将当前数字加入组合current.add(candidates[i]);// 递归调用,下一次递归的 start 为 i + 1,因为每个数字只能使用一次backtrackII(candidates, remaining - candidates[i], i + 1, current, result);// 回溯,移除最后一个数字current.remove(current.size() - 1);}}// 组合总和 III:找出所有相加之和为 n 的 k 个数的组合,组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字public List<List<Integer>> combinationSumIII(int k, int n) {List<List<Integer>> result = new ArrayList<>();// 调用回溯方法backtrackIII(k, n, 1, new ArrayList<>(), result);return result;}private void backtrackIII(int k, int remaining, int start, List<Integer> current, List<List<Integer>> result) {// 如果当前组合的长度等于 k 且剩余值为 0,说明找到了一个有效的组合if (current.size() == k && remaining == 0) {result.add(new ArrayList<>(current));return;}// 如果当前组合的长度大于 k 或者剩余值小于 0,说明当前组合不满足条件if (current.size() > k || remaining < 0) {return;}// 从 start 开始遍历 1 - 9 的数字for (int i = start; i <= 9; i++) {// 将当前数字加入组合current.add(i);// 递归调用,下一次递归的 start 为 i + 1,避免重复使用数字backtrackIII(k, remaining - i, i + 1, current, result);// 回溯,移除最后一个数字current.remove(current.size() - 1);}}public static void main(String[] args) {CombinationSumProblems solution = new CombinationSumProblems();// 测试组合总和 Iint[] candidatesI = {2, 3, 6, 7};int targetI = 7;List<List<Integer>> resultI = solution.combinationSumI(candidatesI, targetI);System.out.println("组合总和 I:和为 " + targetI + " 的所有组合: " + resultI);// 测试组合总和 IIint[] candidatesII = {10, 1, 2, 7, 6, 1, 5};int targetII = 8;List<List<Integer>> resultII = solution.combinationSumII(candidatesII, targetII);System.out.println("组合总和 II:和为 " + targetII + " 的所有组合: " + resultII);// 测试组合总和 IIIint k = 3;int n = 9;List<List<Integer>> resultIII = solution.combinationSumIII(k, n);System.out.println("组合总和 III:和为 " + n + " 的 " + k + " 个数的所有组合: " + resultIII);}
}    

http://www.xdnf.cn/news/4816.html

相关文章:

  • 10. CSS通配符与选择器权重深度解析:以《悯农》古诗为例
  • 比较Facebook与其他社交平台的隐私保护策略
  • RSS 2025|斯坦福提出「统一视频行动模型UVA」:实现机器人高精度动作推理
  • 机器视觉的手机FPC油墨丝印应用
  • 在k8s中,如何实现服务的访问,k8s的ip是变化的,怎么保证能访问到我的服务
  • 数据结构-非线性结构-二叉树
  • G口大带宽服务器线路怎么选
  • 根据窗口大小自动调整页面缩放比例,并保持居中显示
  • Python程序,输入IP,扫描该IP哪些端口对外是开放的,输出端口列表
  • Vue生命周期脚手架工程Element-UI
  • 经济体制1
  • http重新为https
  • 基于FPGA婴儿安全监护系统(蓝牙小程序监测)
  • 2025年渗透测试面试题总结-某服面试经验分享(附回答)(题目+回答)
  • R 语言机器学习:为遥感数据处理开启新视角
  • 二元随机响应(Binary Randomized Response, RR)的翻转概率
  • flink超时未揽收单量统计
  • 【AI提示词】马斯洛需求分析专家
  • 【Linux】socket网络编程之UDP
  • cursor平替,试试 vscode+cline+openrouter 的方案,还能自定义 mcp-server 教程大纲
  • 【算法-链表】链表操作技巧:常见算法
  • 元宇宙虚拟展厅如何制作?
  • 华为网路设备学习-21 路由过滤(filter-policy)
  • 微服务不注册到nacos的方法
  • HTML9:页面结构分析
  • 初识Linux · 传输层协议TCP · 上
  • 坐标系与坐标系数转换
  • 接口自动化测试框架详解(pytest+allure+aiohttp+ 用例自动生成)
  • 一文读懂Nginx应用之 HTTP负载均衡(七层负载均衡)
  • 记录微信小程序掉起半屏失效问题