110.平衡二叉树
1、代码(递归)
/**
* 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 isBalanced(TreeNode root) {
//后序遍历
int height = getHeight(root);
if(height != -1){
return true;
}
return false;
}
public int getHeight(TreeNode node){
if(node == null){
return 0;
}
//这里需要判断左右子树返回的都是-1的情况
int leftHeight = getHeight(node.left);
if(leftHeight == -1){
return -1;
}
int rightHeight = getHeight(node.right);
if(rightHeight == -1){
return -1;
}
if(Math.abs(leftHeight - rightHeight) <= 1){
//
return Math.max(leftHeight,rightHeight) + 1;
}else{
return -1;
}
}
}
2、分析
(1)判断是否是平衡二叉树的依据是**“左右子树高度差绝对值不超过一”。**
(2)因为要求的是高度差,所以要返回左右子树的高度差给根节点,易得这是左右中的顺序,所以程序需要使用后序遍历。
(3)函数参数是根节点,返回值是高度,所以函数返回值为整型。
(4)后序遍历遍历到底部之后判断高度差的绝对值是否小于1,若小于1则记录其高度为1,返回上一层。上一层返回1+左右子树的最大高度,此为上一层的最终高度。
(5)代码:
if(leftHeight == -1){
return -1;
}
这里需要对其单独判断的原因是当函数返回到根节点的时候,若左右子树都为-1,即左右子树都不满足平衡二叉树的定义,但是它们此时的高度差绝对值小于一,可以返回true。所以我们要对其加一个单独的判断,当左右子树的值为-1的时候,函数直接返回-1。
(6)本题需要返回布尔值,为什么要用-1,0来做返回值。因为我们在程序执行的时候需要用到整型变量来累计高度,此时可以使用一个小技巧来避免无法记录高度的情况:用-1表示false,0表示直接返回,其余数值表示我们需要用到的整型变量,到最后真正return的时候用表达式进行判断即可。
257. 二叉树的所有路径
1、代码(递归)
/**
* 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> res = new ArrayList<>();
if(root == null){
return res;
}
List<Integer> paths = new ArrayList<>();
dfs(root,paths,res);
return res;
}
public void dfs(TreeNode node,List<Integer> paths,List<String> res){
paths.add(node.val);
if(node.left == null && node.right == null){
//将路径加入到res
StringBuilder sb = new StringBuilder();
for(int i=0; i<paths.size()-1; i++){
sb.append(paths.get(i)).append("->");
}
sb.append(paths.get(paths.size()-1));
res.add(sb.toString());
//
return;
}
if(node.left != null){
dfs(node.left,paths,res);
paths.remove(paths.size()-1);
}
if(node.right != null){
dfs(node.right,paths,res);
paths.remove(paths.size()-1);
}
}
}
2、分析
(1)这是递归回溯的题目,要回溯的原因是当函数走完一条路径时需要还原到初始时刻,所以我们需要在递归的时候用线性表在add之后进行remove,达到回溯的效果。
(2)如何寻找每一条不同的路径?
通过 if 判断节点的左和右节点是否为空,不为空则进行递归,按照前序遍历的顺序进行。
404.左叶子之和
1、代码(递归)
/**
* 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 int sumOfLeftLeaves(TreeNode root) {
//后序遍历
if(root == null){
return 0;
}
int res = dfs(root);
return res;
}
public int dfs(TreeNode node){
if(node == null){
return 0;
}
//对叶子节点的先行判断,避免遍历叶子节点的左右空节点
//因为本题借助叶子节点的上一个节点进行判断,所以可以在指针指向叶子节点的时候对其先行判断。
if(node.left == null && node.right == null){
return 0;
}
int value = 0;
//对于左叶子节点的判断
if(node.left != null && node.left.left == null
&& node.left.right == null){
value = node.left.val;
}
int leftValue = dfs(node.left);
int rightValue = dfs(node.right);
int res = value + leftValue + rightValue;
return res;
}
}
2、分析
(1)本题若直接对叶子节点进行操作,由于左右叶子的特性一致,导致无法判断是否为左叶子,所以我们可以借鉴操作链表的经验,直接操作左叶子的上一个节点。
(2)代码:
if(node.left == null && node.right == null){
return 0;
}
这里对叶子节点进行先行判断后直接返回,可以直接减少一层递归循环。
(3)这里需要将左叶子节点的值进行相加,所以使用后序遍历将结果返回到根节点,所以每个函数的返回值都要相加并且最终返回到根节点。
文章详细介绍了三种二叉树问题的解决方案:110.平衡二叉树通过后序遍历检查左右子树高度差;257.二叉树的所有路径利用前序遍历获取所有路径;404.左叶子之和通过后序遍历计算左叶子节点的和。每部分都包含递归代码实现和逻辑分析。
358

被折叠的 条评论
为什么被折叠?



