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

二叉树算法

基础知识

二叉树类型:

  1. 满二叉树:节点有两个子节点,且每一层都填满
  2. 完全二叉树:左顺序二叉树,每一层节点从最左节点依次开始
  3. 二叉搜索树:有序二叉树,节点的左子树节点<节点值<节点的右子树节点
  4. 平衡二叉搜索树:二叉搜索树+平衡(左右子树高度差<=1)

存储方式:链表/数组

遍历方式:

深度优先遍历DFS(递归法,迭代法):先往深处走,遇到空节点再往回走  数据结构:栈,先进后出(递归法,迭代法)

  • 前序遍历:中左右
  • 中序遍历:左中右
  • 后序遍历:左右中

观察:前中后,分别对应中的位置不同,其次一左一右;

广度优先遍历BFS(迭代法):一层一层遍历 数据结构:队列 先进先出

  • 层次遍历

节点定义

    class TreeNode{int val;TreeNode left,right;TreeNode(){}TreeNode(int val){this.val = val;}TreeNode(int val,TreeNode left,TreeNode right){this.val = val;this.left = left;this.right = right;}}

算法思路:

  1. 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
  2. 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
  3. 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

DFS

二叉树的前中后序遍历

    public List<Integer> inorderTraversal(TreeNode root){// 1.递归参数和返回值 入参 root 出参 resList<Integer> res = new ArrayList<Integer>();inorder(root,res);return res;}public void inorder(TreeNode root,List<Integer> res){// 2.终止条件  遇到节点if(root == null){return;}// 3.单层递归逻辑res.add(root.val);  // 前序遍历inorder(root.left, res);
//        res.add(root.val);  // 中序遍历inorder(root.right,res);
//        res.add(root.val);  // 后序遍历}

二叉树的最大深度

返还数值的一般都是全局单独定义

    private  int ans = 0;public int maxDepth(TreeNode root){// 1.递归的入参和出参dfs(root,0);return ans;}public void dfs(TreeNode root,int depth){// 2.终止条件if(root == null){return;}// 3。单层递归逻辑depth++;ans = Math.max(ans,depth);dfs(root.left,ans);dfs(root.right,ans);}

翻转二叉树

   public TreeNode invertTree(TreeNode root){dfs(root);return root;}public void dfs(TreeNode root){if(root == null){return;}// 节点互换TreeNode temp = root.left;root.left = root.right;root.right = temp;// 递归dfs(root.left);dfs(root.right);}

对称二叉树

   public boolean isSymmetric(TreeNode root){if(root == null){return true;}else {return dfs(root.left,root.right);}}public boolean dfs(TreeNode left,TreeNode right){if(left == null && right == null){return true;}if(left == null || right == null || left.val!=right.val){return false;}return dfs(left.right,right.left) && dfs(left.left,right.right);}

二叉树直径

思路:

    private int ans;public int diameterOfBinaryTree(TreeNode root){dfs(root);return ans;}private int dfs(TreeNode root){if(root == null){return -1;}int leftLen = dfs(root.left)+1;int rightLen = dfs(root.right)+1;ans = Math.max(ans,leftLen+rightLen);return Math.max(leftLen,rightLen);}

有序数组转二叉搜索树(前序遍历)

思路:

  public TreeNode sortedArrayToBST(int[] nums){return dfs(nums,0,nums.length-1);}public TreeNode dfs(int[] nums,int left,int right){if(left > right){return null;}int mid = left+(right-left)/2;TreeNode root = new TreeNode(nums[mid]);root.left = dfs(nums,left,mid-1);root.right = dfs(nums,mid+1,right);return root;}

验证二叉搜索树

思路:

class Solution {public boolean isValidBST(TreeNode root) {return dfs(root, null, null); // 初始时无边界限制}private boolean dfs(TreeNode node, Integer min, Integer max) {if (node == null) {return true;}// 检查当前节点值是否在 (min, max) 范围内if ((min != null && node.val <= min) || (max != null && node.val >= max)) {return false;}// 递归检查左子树(最大值限制为当前节点值)// 递归检查右子树(最小值限制为当前节点值)return dfs(node.left, min, node.val) && dfs(node.right, node.val, max);}
}

二叉搜索树第k小的树

思路:将二叉树转化为数组,并对数组排序,遍历数组到k-1(从0索引)位置;

k--与--k前者先比较后减 后者先减后比较

应该是利用搜索树特性

class Solution {private int k;public int kthSmallest(TreeNode root, int k) {this.k = k;return dfs(root);}private int dfs(TreeNode node){if(node == null){return -1;}int leftRes = dfs(node.left);if(leftRes != -1){return leftRes;}if(--k == 0){return node.val;}return dfs(node.right);}
}

路径和Ⅲ

思路:把每个节点都当作根节点向下检索

双递归

class Solution {public int pathSum(TreeNode root, long targetSum) {if(root == null){return 0;}int ret = rootSum(root,targetSum);ret += pathSum(root.left, targetSum);ret += pathSum(root.right, targetSum);return ret;}public int rootSum(TreeNode root ,long targetSum){int ret = 0;if(root == null){return 0;}int sum = root.val;if(sum == targetSum){ret++;}ret += rootSum(root.left, targetSum - sum);ret += rootSum(root.right, targetSum - sum);return ret;}}

二叉树最近公共先祖

思路:

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {return sfz(root, p, q);}public TreeNode sfz(TreeNode node,TreeNode p,TreeNode q){if(node == null){return null;}if(node.val == p.val || node.val == q.val){return node;}TreeNode left = sfz(node.left,p,q);TreeNode right = sfz(node.right,p,q);if(left!=null&&right!=null){return node;}return left !=null?left:right;}
}

二叉树最大路径和

思路:

class Solution {public int maxPathSum(TreeNode root) {int[] max = new int[1];max[0] = Integer.MIN_VALUE;getMaxSum(root,max);return max[0];}public int getMaxSum(TreeNode root,int[] max){if(root == null){return 0;}int left = Math.max(0,getMaxSum(root.left,max));int right = Math.max(0,getMaxSum(root.right,max));int currentMax = root.val + left +right;max[0] = Math.max(max[0],currentMax);return root.val+Math.max(left,right);}
}

 

BFS

适用场景:「层序遍历」、「最短路径」

// 二叉树的层序遍历
void bfs(TreeNode root) {Queue<TreeNode> queue = new ArrayDeque<>();queue.add(root);while (!queue.isEmpty()) {int n = queue.size();for (int i = 0; i < n; i++) { // 变量 i 无实际意义,只是为了循环 n 次TreeNode node = queue.poll();if (node.left != null) {queue.add(node.left);}if (node.right != null) {queue.add(node.right);}}}
}

二叉树层序遍历

   public List<List<Integer>> levelOrder(TreeNode root){List<List<Integer>> res = new ArrayList<>();Queue<TreeNode> queue = new ArrayDeque<>();if(root != null){queue.add(root);}while (!queue.isEmpty()){int n = queue.size();List<Integer> level = new ArrayList<>();for(int i =0;i<n;i++){TreeNode node = queue.poll();level.add(node.val);if(node.left!=null){queue.add(node.left);}if(node.right!=null){queue.add(node.right);}}res.add(level);}return res;}

二叉树最短路径

 

 

 

 

 

 

 

 

http://www.dtcms.com/a/316445.html

相关文章:

  • 02-算法
  • Java后端高频面试题
  • EP02:【DL 第二弹】张量的索引、分片、合并以及维度调整
  • 如何选择正确的体育/电竞数据接口服务商?
  • 力扣148:排序链表
  • Android 开发中,HandlerThread、IntentService 和 AsyncTask区别对比
  • Pytorch基础入门2
  • C++面向对象编程基础:从类定义到封装机制详解
  • 【Linux网络编程】socket基础
  • 风丘助力混合动力汽车工况测试:精准采集整车信号解决方案
  • Datawhale AI夏令营 第三期 task2 稍微改进
  • P1026 [NOIP 2001 提高组] 统计单词个数
  • 计算机网络:详解路由器如何转发子网数据包
  • Java JDBC连接池深度解析与实战指南
  • SAP PP CK466
  • 解决docker load加载tar镜像报json no such file or directory的错误
  • jQuery中Ajax返回字符串处理技巧
  • Window.structuredClone() 指南
  • 基于深度学习钢铁表面缺陷检测系统(yolov8/yolov5)
  • 《算法导论》第 3 章 - 函数的增长
  • 本地配置运行https协议
  • Spring依赖注入:从原理到实践的自学指南
  • Linux 调度器函数sched_*系统调用及示例
  • 【数据结构入门】单链表和数组的OJ题(1)
  • 基于ARM+FPGA光栅数据采集卡设计
  • OpenCV学习 day5
  • 从「同步」到「异步」:用 aiohttp 把 Python 网络 I/O 榨到极致
  • Python--OCR(2)
  • 微算法科技(NASDAQ:MLGO)基于量子重加密技术构建区块链数据共享解决方案
  • 算法438. 找到字符串中所有字母异位词