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

刷算法Leetcode---9(二叉树篇Ⅲ)

前言

        本文是跟着代码随想录的二叉树顺序进行刷题并编写的  代码随想录

        二叉树的题目较多,就多分了几次写,这是第三篇

        这是力扣刷算法的其他文章链接:刷算法Leetcode文章汇总

二叉树篇Ⅲ

(1)226. 翻转二叉树 

        dfs,对每个节点反转左右子树

class Solution {public TreeNode invertTree(TreeNode root) {if(root==null)return null;TreeNode left = invertTree(root.left);TreeNode right = invertTree(root.right);root.left=right;root.right=left;return root;}
}

(2)101. 对称二叉树 

        ①dfs,左右子树同时递归并进行判断

class Solution {public boolean isSymmetric(TreeNode root) {if(root == null) return true;return isSymmetricNode(root.left, root.right);}public boolean isSymmetricNode(TreeNode node1, TreeNode node2){if(node1 == null && node2 == null) return true;if(node1 == null || node2 == null) return false;if(node1.val != node2.val) return false;return isSymmetricNode(node1.left, node2.right)&&isSymmetricNode(node1.right,node2.left);}
}

        ②bfs+队列,左右比较节点依次入队。注意空节点也要加入队列,代表左右位置

        注意:ArrayDeque线程不安全不能加入空节点,因此使用LinkedList实现队列

class Solution {private Deque<TreeNode> queue;public boolean isSymmetric(TreeNode root) {if(root == null) return true;queue = new LinkedList<TreeNode>();queue.addLast(root.left);queue.addLast(root.right);while(!queue.isEmpty()){TreeNode node1 = queue.pollFirst(), node2 = queue.pollFirst();if(node1 == null && node2 == null) continue;if(node1 == null || node2 == null) return false;if(node1.val != node2.val) return false;queue.addLast(node1.left);queue.addLast(node2.right);queue.addLast(node1.right);queue.addLast(node2.left);}return true;}
}

(3)222. 完全二叉树的节点个数

        ①bfs+队列,同102题(可见上一篇),层序遍历计数即可

        ②dfs,同102题(可见上一篇),递归左右节点计数

        ③二分查找+位运算,使用二分查找确定分支,位运算选择左右节点。

        具体操作:先找最左节点确定层数level(根为第零层),总节点数min=1<<(level),max=((1<<(level+1))-1,在min和max中进行二分查找。若mid处的node空,取左半部分迭代,若node不空取右半部分迭代;确定level层某个节点是否存在:node从根开始,根据与half=1<<(level-1)进行位与,即从左第二位开始取,为0左移为1右移,循环half>>1,判断node是否空。

        特点:使用层数位的二进制可表示某一次的所有节点,位运算确定左右的选择,0左移1右移

class Solution {public int countNodes(TreeNode root) {if(root==null)return 0;TreeNode node = root;int level=0;while(node.left!=null){node=node.left;level++;}int min = 1<<level, max = (1<<(level+1))-1;while(min<max){int mid = (max-min+1)/2+min;if(exist(root,level,mid)) min = mid;else max=mid-1;}return min;}private boolean exist(TreeNode root,int level,int mid){int bits = 1<<(level-1);TreeNode node = root;while(node!=null&&bits>0){if((bits&mid)==0)node=node.left;else node=node.right;bits>>=1;}return node!=null;}
}

(4)110. 平衡二叉树 

        ①dfs自下而上,先判断左右子树,并将高度回溯,返回-1进行剪枝

class Solution {public boolean isBalanced(TreeNode root) {return getDepth(root)>=0;}private int getDepth(TreeNode node){if(node==null) return 0;int left = getDepth(node.left);int right = getDepth(node.right);if(left==-1||right==-1||Math.abs(left-right)>1)return -1;return Math.max(left,right)+1;}
}

        ②dfs自上而下,先计算根节点再判断左右子树

class Solution {public boolean isBalanced(TreeNode root) {if(root==null)return true;return Math.abs(getDepth(root.left)-getDepth(root.right))<=1&&isBalanced(root.left)&&isBalanced(root.right);}private int getDepth(TreeNode node){if(node==null) return 0;return Math.max(getDepth(node.left),getDepth(node.right))+1;}
}

(5)257. 二叉树的所有路径 

        ①dfs,递归不空节点和已有路径,为叶子节点时记录结果

class Solution {private List<String> res;public List<String> binaryTreePaths(TreeNode root) {res = new ArrayList<>();if(root==null)return res;dfs(root,Integer.toString(root.val));return res;}private void dfs(TreeNode node,String s){if(node.left==null&&node.right==null)res.add(s);if(node.left!=null)dfs(node.left,s+"->"+Integer.toString(node.left.val));if(node.right!=null)dfs(node.right,s+"->"+Integer.toString(node.right.val));}
}

        ②bfs+队列,nodeQueue记录节点,pathQueue记录每个节点对应的路径,若为叶子节点则记录结果

class Solution {private List<String> res;private Deque<TreeNode> nodeQueue;private Deque<String> pathQueue;public List<String> binaryTreePaths(TreeNode root) {res = new ArrayList<>();if(root==null)return res;nodeQueue = new ArrayDeque<>();pathQueue = new ArrayDeque<>();nodeQueue.addLast(root);pathQueue.addLast(Integer.toString(root.val));while(!nodeQueue.isEmpty()){TreeNode tempNode = nodeQueue.pollFirst();String tempPath = pathQueue.pollFirst();if(tempNode.left==null&&tempNode.right==null)res.add(tempPath);if(tempNode.left!=null){nodeQueue.addLast(tempNode.left);pathQueue.addLast(tempPath+"->"+Integer.toString(tempNode.left.val));}if(tempNode.right!=null){nodeQueue.addLast(tempNode.right);pathQueue.addLast(tempPath+"->"+Integer.toString(tempNode.right.val));}}return res;}
}

(6)404. 左叶子之和 

        ①bfs+队列,同102题层序遍历(可看上一篇),记录每层第一个节点的和

        ②dfs,递归并记录是否为左孩子,若为左孩子并为叶子节点,则记录值

class Solution {private int res;public int sumOfLeftLeaves(TreeNode root) {if(root==null)return 0;res=0;dfs(root,false);return res;}private void dfs(TreeNode node, boolean isLeft){if(isLeft&&node.left==null&&node.right==null){res+=node.val;return;}if(node.left!=null)dfs(node.left,true);if(node.right!=null)dfs(node.right,false);}
}

        ③dfs,有左孩子时判断左孩子是否为叶子节点,极简版

class Solution {public int sumOfLeftLeaves(TreeNode root) {if(root==null)return 0;return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right)+ (root.left!=null&&root.left.left==null&&root.left.right==null ? root.left.val : 0);}
}

(7)513. 找树左下角的值 

        ①bfs+队列,同102题层序遍历(可见上一篇),记录最新一层第一个节点的值。或者每层从右到左遍历,记录的最后一个节点即为结果

        ②dfs,递归每个节点的层数,并记录最底层的层数,遇到新层记录结果

class Solution {private int maxDepth = 0, res = 0;public int findBottomLeftValue(TreeNode root) {dfs(root,1);return res;}private void dfs(TreeNode node,int depth){if(node==null)return;if(depth>maxDepth){res = node.val;maxDepth = depth;}dfs(node.left,depth+1);dfs(node.right,depth+1);}
}

(8)112. 路径总和

        ①dfs,同257题,当为叶子节点且路径和满足时返回true

class Solution {private int target;public boolean hasPathSum(TreeNode root, int targetSum) {if(root==null)return false;target = targetSum;return dfs(root,0);}private boolean dfs(TreeNode node,int sum){if(node==null)return false;sum+=node.val;if(node.left==null&&node.right==null&&sum==target)return true;return dfs(node.left,sum)||dfs(node.right,sum);}
}

        ②bfs+队列,同257题,nodeQueue记录节点,sumQueue记录节点对应的和,当取出的节点为叶子并且和为目标,返回true

        ③dfs,递归targetSum-root.val,若当前节点为叶子节点,则判断节点值是否与递归和相同

class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {if(root==null)return false;if(root.left==null&&root.right==null)return root.val==targetSum;return hasPathSum(root.left,targetSum-root.val)||hasPathSum(root.right,targetSum-root.val);}
}

二叉树篇Ⅲ总结

        ①bfs和dfs都可以很方便的遍历二叉树

        ②对于翻转二叉树、对称二叉树、平衡二叉树这种题,使用dfs非常方便

        ③dfs分为自下而上(从叶子到根)和自上而下(从根到叶子)两种,按题目需求选择,如110和112题

        ④对于222题的完全二叉树问题,使用二分法缩短查找时间,使用层数位二进制表示一层集结点,使用位运算确定一条到叶子节点的路径

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Vue.js 中属性绑定的详细解析:冒号 `:` 和非冒号的区别
  • 1125 子串与子列
  • 【3】迁移学习模型
  • 软件开发面试题(C#语言,.NET框架)
  • 【Linux进阶】Linux目录配置,FHS
  • MyBatis学习笔记-参数转义处理
  • App UI性能测试 - PerfDog使用全教程
  • 如何实现一套键盘鼠标控制两台计算机(Mouse Without Borders快速上手教程)
  • Docker搭建MySQL双主复制详细教程
  • 【前端】从零开始学习编写HTML
  • HNU小学期BSP软件编程基础十道测试题
  • Java学习
  • Linux基础IO
  • 海外金融机构银行保险证券数字化转型营销销售数字化成功案例讲师培训师讲授开户销售营销客户AI人工智能创新思维
  • 红酒知识百科:从入门到精通
  • 【React系列】如何构建React应用程序
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • 2017 年终总结 —— 在路上
  • 4. 路由到控制器 - Laravel从零开始教程
  • Create React App 使用
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • Docker入门(二) - Dockerfile
  • flask接收请求并推入栈
  • JavaScript 基本功--面试宝典
  • Java超时控制的实现
  • Java程序员幽默爆笑锦集
  • magento2项目上线注意事项
  • nodejs:开发并发布一个nodejs包
  • Redis 懒删除(lazy free)简史
  • uva 10370 Above Average
  • 来,膜拜下android roadmap,强大的执行力
  • 算法---两个栈实现一个队列
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 责任链模式的两种实现
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • # SpringBoot 如何让指定的Bean先加载
  • #if和#ifdef区别
  • #NOIP 2014#Day.2 T3 解方程
  • #如何使用 Qt 5.6 在 Android 上启用 NFC
  • #职场发展#其他
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (ZT)出版业改革:该死的死,该生的生
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (区间dp) (经典例题) 石子合并
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (五)关系数据库标准语言SQL
  • (一)VirtualBox安装增强功能
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .NET 的程序集加载上下文
  • .Net6使用WebSocket与前端进行通信
  • .NET项目中存在多个web.config文件时的加载顺序
  • @ 代码随想录算法训练营第8周(C语言)|Day57(动态规划)
  • @requestBody写与不写的情况