前言
再熟悉遍历的基础上,掌握二叉树常见的变换手段,例如路径求和;节点值向上汇总求和,层的求和等
104:二叉树的最大深度
题目要求:给定一个二叉树root,要求返回最大深度。
核心思想(递归)
运用递归的思想,遍历二叉树的左右节点,得到最大深度
代码实现
java
class Solution {
public int maxDepth(TreeNode root) {
if(root==null){
return 0;
}
//遍历左子树
int leftDepth=maxDepth(root.left);
//遍历右子树
int rightDepth=maxDepth(root.right);
return Math.max(leftDepth,rightDepth)+1;
}
}
总结
递归属于抽象理解,想要掌握递归思路,要再脑海中想象出递归的流程步骤就非常容易掌握。
98:验证二叉搜索树
题目要求:
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 严格小于 当前节点的数。
节点的右子树只包含 严格大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
核心思路(递归+中序遍历)
一句话:
用中序遍历模拟节点从小到大的顺序,只要发现顺序不对,就不是BST
递归中序遍历整棵树
维护一个变量prev,保存上一个访问节点的值
当前节点的值必须严格大于prev
代码实现
java
long prev=Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
return inorder(root);
}
public boolean inorder(TreeNode node){
if(node==null){return true;}
//左
if(!inorder(node.left)){return false;}
//中
if(node.val<=prev){return false;}
prev=node.val;
//右
return inorder(node.right);
}
总结
通过递归中序遍历整棵树,来判断是否满足二叉搜索树
112:路径总和
题目要求:给定一个二叉树和一个整数 targetSum,判断树中是否存在从根节点到叶子节点的路径,使得路径上所有节点值之和等于 targetSum。
核心思路
递归遍历树:前序遍历(根 左 右)
更新剩余目标值:每到一个节点,减去当前节点值
到达叶子节点时检查剩余目标值
如果左右子树都不满足,返回false
代码实现
java
if(root==null) return false;
if(root.left==null||root.righ==null){return targetSum==root.val;}
return hasPathSum(root.left,targetSum-root.val)||hasPathSum(root.left,targetSum-root.val);
总结
通过递归来遍历整个树。每次遍历完成后都更新targetSum的值,最后与叶子节点的值进行比较判断。
108:将有序数组转换位二叉搜索树
题目要求:给定一个整数数组nums,元素已经按照升序排列
要求:讲起转换为一个平衡二叉搜索树
核心思路
找到数组中间元素,作为根节点
中间元素左边的,作为左子树
右边的作为右子树
递归完成左右子树,返回根节点
代码实现
java
public TreeNode sortedArrayToBST(int[] nums) {
return build(nums,0,nums.length-1);
}
public TreeNode build(int[] nums,int left,int right){
//终止条件
if(left>right)return null;
//找中点
int mid=left+(rigth-left)/2;
//创建根节点
TreeNode root=new TreeNode(nums[mid]);
//递归遍历创建左子树
root.left=build(nums,left,mid-1);
//递归创建右子树
root.rigth=build(nums,mid+1;right);
return root;
}
总结
二叉树中的left和right不是定值,题目会随着递归而更新。本题的核心思路就是"
创建根节点(中点),通过递归的方法创建左子树与右子树,最后返回根节点
662:二叉树最大宽度
题目要求;给定一个二叉树根节点root
要求:树中最大宽度(最左节点到最右节点的宽度,null也算)
核心思路
- BFS(广度优先搜索)遍历每一层节点
- 每个节点一个编号index
根节点 index = 1
左子节点 index = parent_index * 2
右子节点 index = parent_index * 2 + 1 - 每一层
记录 最左节点编号 start 和 最右节点编号 end
层宽 = end - start + 1 - 遍历所有层,返回最大宽度
代码实现
java
if(root==null) return 0;
int maxWidth=0;
//创建队列
Queue<Pair<TreeNode,Integer>> queue=new LinkedList<>();
queue.offer(new Pair(root,1));//根节点编号为1
//为后面循环作预处理
while(!queue.isEmpty()){
int size=queue.size();
int start=queue.peek.getValue();
int end=start;
for(int i=0;i<size;i++){
Pair<TreeNode,Integer> pair=queue.poll();
TreeNode node=pair.getKey();
int index=pair.getValue();
end=index;//更细右编号
if(node.left!=null) queue.offer(new Pair(node.left,index*2));
if(node.right!=null) queue.offer(new Pair(node.right,index*2+1));
}
mxaWidth=Math.max(maxwidth,end-start+1);
}
return maxWidth;
总结
用编号+BFS的方法来解决
掌握编号的计算
199:二叉树的右视图
题目要求:给定一个二叉树根节点root
要求:返回从右侧看到的节点值
核心思路
- BFS遍历树,每层按顺序处理节点
- 每一层的最后一个节点就是结果
- 将每层最后一个节点加入结果列表
代码实现
java
List<Integer> res=new ArrayListed<>();
if(root==null) return res;
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty){
int size=queue.size();
for(int i=0;i<size;i++){
TreeNode node=queue.poll();
//当前层最后一个节点,加入结果
if(i==size-1) res.add(node.val);
if(node.left!=null) queue.offer(node.left);
if(node.right!=null) queue.offer(node.right);
}
}
return res;
总结
本题要求最后一个节点,想到用BFS层遍历来获取最后一个节点