一、110. 平衡二叉树 - 力扣(LeetCode)
1.1题目
给定一个二叉树,判断它是否是
平衡二叉树
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:true
示例 2:
输入:root = [1,2,2,3,3,null,null,4,4] 输出:false
1.2思路分析
当前根节点的高度为其左孩子右孩子中高度的最大值加一;
二叉树的深度是指从根节点到当前节点最长简单路径边的条数;
二叉树的高度是指从该节点到叶子节点的最长简单路径边的条数。
1.3代码实现
/**
* 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;
* }
* }
*/
class Solution {
boolean result = true;
public boolean isBalanced(TreeNode root) {
fun(root);
return result ;
}
public int fun(TreeNode root){
if( root == null) return 0;
int left = fun(root.left)+1;
int right = fun(root.right)+1;
if(Math.abs(left-right) > 1) result = false;
return Math.max(left,right);
}
}
二、257. 二叉树的所有路径 - 力扣(LeetCode)
2.1题目
给你一个二叉树的根节点 root
,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [1,2,3,null,5] 输出:["1->2->5","1->3"]
示例 2:
输入:root = [1] 输出:["1"]
2.2思路分析
记得递归和回溯不分家。
2.3代码实现
/**
* 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;
* }
* }
*/
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
if(root == null) return result;
fun(root,path,result);
return result;
}
public void fun(TreeNode root , List<Integer> path,List<String>result){
// 先将根节点放入到路径中
path.add(root.val);
//判断是否递归到跟节点
if(root.left == null && root.right == null){
// 此时可以将路径添加到path中
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i < path.size() ; i++){
sb.append(path.get(i)).append("->");
}
String sb1 = sb.toString();
sb1 = sb1.substring(0,sb1.length()-2);
result.add(sb1);
return;
}
if(root.left != null){
fun(root.left,path,result);
// 回溯
path.remove(path.size()-1);
}
if(root.right != null){
fun(root.right,path,result);
// 回溯
path.remove(path.size()-1);
}
}
}
三、112. 路径总和 - 力扣(LeetCode)
3.1题目
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22 输出:true 解释:等于目标和的根节点到叶节点路径如上图所示。
示例 2:
输入:root = [1,2,3], targetSum = 5 输出:false 解释:树中存在两条根节点到叶子节点的路径: (1 --> 2): 和为 3 (1 --> 3): 和为 4 不存在 sum = 5 的根节点到叶子节点的路径。
示例 3:
输入:root = [], targetSum = 0 输出:false 解释:由于树是空的,所以不存在根节点到叶子节点的路径。
3.2思路分析
使用递归法先判断递归的所有终止条件,然后根据题设要求写出递归表达式。
3.3代码实现
/**
* 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;
* }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) return false;
boolean result = fun(root , targetSum-root.val);
return result;
}
public boolean fun(TreeNode node , int count){
if(node.left == null && node.right == null && count == 0) return true;
if(node.left == null && node.right == null) return false;
// 遇到叶子节点直接返回
if(node.left != null ){
count -= node.left.val;
if(fun(node.left,count)) return true;
// 回溯
count += node.left.val;
}
if(node.right != null){
count -= node.right.val;
if(fun(node.right,count)) return true;
// 回溯
count += node.right.val;
}
return false;
}
}
四、113. 路径总和 II - 力扣(LeetCode)
4.1题目
给你二叉树的根节点 root
和一个整数目标和 targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 输出:[[5,4,11,2],[5,8,4,5]]
示例 2:
输入:root = [1,2,3], targetSum = 5 输出:[]
示例 3:
输入:root = [1,2], targetSum = 0 输出:[]
4.2思路分析
这个题和第二个题类似,不同的是要保存所有的路径信息,而不是单纯的存在就行。
4.3代码实现
/**
* 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;
* }
* }
*/
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> resultList = new ArrayList<List<Integer>>();
if(root == null) return resultList;
// 定义结果数组
List<Integer> path = new ArrayList<Integer>();
//先减去根节
fun(root, targetSum-root.val,resultList,path);
return resultList;
}
public void fun(TreeNode root , int targetSum, List<List<Integer>> resultList,List<Integer> path ){
// 先将根节点加入到路径中
path.add(root.val);
if(root.left == null && root.right == null ){
if(targetSum == 0){
// 此时路径满足条件 将其添加到最终结果中
resultList.add(new ArrayList<Integer>(path));
}
// 当结果不满足时直接返回
return;
}
// if(root.left == null && root.right == null) {
// return;
// }
if(root.left != null){
targetSum -= root.left.val;
fun(root.left,targetSum,resultList,path);
// 不满足条件时回溯
targetSum += root.left.val;
path.remove(path.size()-1);
}
if(root.right != null){
targetSum -= root.right.val;
fun(root.right,targetSum,resultList,path);
// 不满足条件时回溯
targetSum += root.right.val;
path.remove(path.size()-1);
}
}
}
五、106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
5.1题目
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3] 输出:[3,9,20,null,null,15,7]
示例 2:
输入:inorder = [-1], postorder = [-1] 输出:[-1]
提示:
1 <= inorder.length <= 3000
postorder.length == inorder.length
-3000 <= inorder[i], postorder[i] <= 3000
inorder
和postorder
都由 不同 的值组成postorder
中每一个值都在inorder
中inorder
保证是树的中序遍历postorder
保证是树的后序遍历
5.2思路分析
对数组进行不断切片
-
第一步:如果数组大小为零的话,说明是空节点了。
-
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
-
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
-
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
-
第五步:切割后序数组,切成后序左数组和后序右数组
-
第六步:递归处理左区间和右区间
5.3代码实现
/**
* 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;
* }
* }
*/
class Solution {
Map<Integer,Integer> map;
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<>();
for(int i = 0 ; i<inorder.length;i++){
map.put(inorder[i],i);
}
return fun(inorder,0,inorder.length,postorder,0,postorder.length);
}
public TreeNode fun(int[] inorder,int inBegin, int inEnd, int[] postorder,int posBegin,int posEnd){
// 先判断是否为空节点
if(inBegin >= inEnd && posBegin >= posEnd){
return null;
}
// 找到后续遍历的最后一个元素在中序遍历中的位置
int rootIndex = map.get(postorder[posEnd-1]);
// 构造新的节点
TreeNode root = new TreeNode(inorder[rootIndex]);
int lenOfLeft = rootIndex-inBegin;
// 遍历左子树(左闭右开)
root.left=fun(inorder,inBegin,rootIndex,postorder,posBegin,posBegin+lenOfLeft);
// 遍历右子树
root.right=fun(inorder,rootIndex+1,inEnd,postorder,posBegin+lenOfLeft,posEnd-1);
return root;
}
}
六、105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
6.1题目
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1] 输出: [-1]
6.2思路分析
同第5题
6.3代码实现
/**
* 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;
* }
* }
*/
class Solution {
Map<Integer,Integer>map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
map = new HashMap<>();
// 遍历中序数组,并将其放入到map中
for(int i = 0 ; i<inorder.length;i++){
map.put(inorder[i],i);
}
return fun(preorder,0,preorder.length,inorder,0,inorder.length);
}
public TreeNode fun(int[] preorder, int preBegin, int preEnd,int[] inorder, int inBegin,int inEnd){
// 判断是否为空节点
if(preBegin >= preEnd && inBegin >= inEnd){
return null;
}
//在中序遍历中找到根节点的下表
int rootIndex = map.get(preorder[preBegin]);
// 生成新的树节点
TreeNode root = new TreeNode(preorder[preBegin]);
int len = rootIndex-inBegin;
// 生成根节点的左子树与右子树
root.left = fun(preorder,preBegin+1,preBegin+1+len,inorder,inBegin,rootIndex);
root.right = fun(preorder,preBegin+1+len,preEnd,inorder,rootIndex+1,inEnd);
return root;
}
}