二叉树的最大深度104
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
1.必须从根节点开始,到叶子节点截至,返回最多节点数目(最长路径数+1)
2.后序遍历
public class 二叉树的最大深度 {
// Definition for a binary tree node.
public int maxDepth(TreeNode root) {
return getMaxDepth(root);
}
//后序遍历
//返回每一级 最大深度
private int getMaxDepth(TreeNode root){
终止条件:当树为空时结束递归,并返回当前深度0
if(root==null) return 0;
//左右二选一 最大
//递归改变:+1 包括根节点
//root的左、右子树的最大深度
int left=getMaxDepth(root.left);
int right=getMaxDepth(root.right);
//后序遍历:本级递归需要完成的任务
return Math.max(left,right)+1;
}
}
//迭代法
//使用 DFS 策略访问每个结点,同时在每次访问时更新最大深度。
//从包含根结点且相应深度为 1 的栈开始。然后我们继续迭代:将当前结点弹出栈并推入子结点。每一步都会更新深度。
二叉树的直径(两节点的最长路径)543
给定一棵二叉树,你需要计算它的直径长度。
一棵二叉树的直径长度是任意两个结点路径长度中的最大值。
这条路径可能穿过也可能不穿过根结点。
1.与104区别 :可能不经过根节点 所以使用了全局变量存放最大值;
2.类似 :104 1372 1367
3.后序遍历
//二叉树的最大直径 左子树+右子树
//找到一个节点 从该节点到左右两边叶子节点为止 两边边数和(经过的节点数-1)
public class 二叉树的直径 {
//使用全局变量来维护最大值
int max;//最长路径经过的节点个数 路径长度=节点个数-1
public int diameterOfBinaryTree(TreeNode root) {
max=1;
getDepth(root);
return max-1;//节点个数-1
}
//
public int getDepth(TreeNode root){//以root为根节点的深度(左右中最大)
//终止条件:访问到空节点 null时 返回深度为0
if(root==null) return 0;//终止
//左子树深度
int leftDia=getDepth(root.left);//递归 左子树
//右子树深度
int rightDia=getDepth(root.right);//递归 右子树
//后序遍历
//本轮所需要做的事:
//与104 二叉树最大深度差异点:更新“根节点” 更新最大深度
max=Math.max(leftDia+rightDia+1,max);// 计算当前根节点的深度,即L+R+1 并更新 完整整个树中最大的(最大深度)
//返回当前节点的最大深度
return Math.max(leftDia,rightDia)+1;//返回该节点为根的子树的深度
}
}
最长同值路径687
给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。
注意:两个节点之间的路径长度由它们之间的边数表示。
1.起始不一定是根节点,求最大 全局变量维护
2.访问节点的值 条件:同值 连接
3.后序遍历
public class 最长同值路径 {
//可以不经过根节点,即“根节点”可以改变
//求所有情况最大值
//全局变量维护更新
int max;
public int longestUnivaluePath(TreeNode root) {
//
max=0;
if(root==null) return 0;
getMaxPath(root);
return max;
}
//最长同值路径:返回单侧最长路径(包含root)在内;
//以node为根(不考虑父节点,父节点在不在最长路径中是父节点管的事)且包含node.val值本身所在的**单侧**“最长“同值路径的长度
//条件 :同值 连接
public int getMaxPath(TreeNode root){
//递归终止条件:访问到空节点
if(root==null) return 0;
//获取左右子树的最大深度
int left=getMaxPath(root.left);
int right=getMaxPath(root.right);
//单次递归需要做的事:
int leftSum=0,rightSum=0;
//防止空指针异常
//存在左子节点且左子节点的值与当前根节点的值相同
if(root.left!=null&&root.left.val==root.val)
leftSum=left;
//存在右子节点且右子节点的值与当前根节点的值相同
if(root.right!=null&&root.right.val==root.val)
rightSum=right;
//维护更新最大值
max=Math.max(max,leftSum+rightSum);
//返回当前根节点的最大深度
return Math.max(leftSum,rightSum)+1;
}
}
二叉树中的最大路径和124
给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。
该路径至少包含一个节点,且不一定经过根节点。
1.后序遍历
2.
public class 二叉树中的最大路径和 {
//全局变量 存放更新最大路径和
int maxSum=Integer.MIN_VALUE;//由于节点值和可能出现负的,此时不能设置初始值为0,设为最小整数
public int maxPathSum(TreeNode root) {
if(root==null) return 0;
getMaxSum(root);
// maxPathSum(root.left);
// maxPathSum(root.right);
return maxSum;
}
private int getMaxSum(TreeNode root){
//递归终止条件:访问到空节点,返回:所经过的节点值的和为0
if(root==null) return 0;
// if(root.left==null&&root.right==null) return 0;叶子节点应该返回叶子节点的值,此行错误
//左右子树的节点值的和
//有可能和为负数,此时舍弃该子树 和用0取代
int left=Math.max(getMaxSum(root.left),0);
int right=Math.max(getMaxSum(root.right),0);
//本次递归所需要做的事情:
//1.更新最大值
maxSum=Math.max(root.val+left+right,maxSum);
//返回 根节点在内,单侧 最大 节点值的和
int sum=root.val+Math.max(left,right);
return sum;
}
}
平衡二叉树110
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
1.从根节点开始 到 叶子节点 截止 求高度 (返回节点数) 返回是否平衡
2.后序遍历
/**
* 后序遍历
* 判断left子树和right子树是否是平衡二叉树,如果不是则直接返回false。
* 再判断两树高度差是否不大于1,如果大于1也直接返回false。
* 否则说明以root为节点的子树是平衡二叉树,返回高度
*/
public class 平衡二叉树 {
public boolean isBalanced(TreeNode root) {
return height(root)!=-1;
}
//对于一颗树,它是一个平衡二叉树需要满足三个条件:
//它的左子树是平衡二叉树;
//它的右子树是平衡二叉树;
//它的左右子树的高度差不大于1。
private int height(TreeNode root){
//递归终止条件:没有节点了,高度为0
if(root==null) return 0;
//本轮所需要做的:
//不平衡的情况有3种:左树不平衡、右树不平衡、左树和右树差的绝对值大于1
int leftHeight=height(root.left);
//左树不平衡
if(leftHeight==-1) return -1;
int rightHeight=height(root.right);
//右树不平衡
if(rightHeight==-1) return -1;
//左树和右树差的绝对值大于1
if(Math.abs(leftHeight-rightHeight)>=2)
return -1;
//返回值:左右子树最高高度+1: 即本节点所在的树的高度
return Math.max(leftHeight,rightHeight)+1;
}
}
二叉树中的最长交错路径1372
给你一棵以 root 为根的二叉树,二叉树中的交错路径定义如下:
选择二叉树中 任意 节点和一个方向(左或者右)。
如果前进方向为右,那么移动到当前节点的的右子节点,否则移动到它的左子节点。
改变前进方向:左变右或者右变左。
重复第二步和第三步,直到你在树中无法继续移动。
交错路径的长度定义为:访问过的节点数目 - 1(单个节点的路径长度为 0 )。
请你返回给定树中最长 交错路径 的长度。
1.类似于
2.多一个变量,记录当前方向
public class 二叉树中的最长交错路径 {
//任意节点 不一定是根节点开始
//全局存储维护更新最大路径
//左变右 右变左 初始二选一 每步记录当前应该走的方向
//记录当前走过的路径
int max;
public int longestZigZag(TreeNode root) {
max=0;
longestZigZag(root,true);
// longestZigZag(root, false);加不加都正确,不过加了速度7ms变8ms
return max;
}
public int longestZigZag(TreeNode root,boolean isLeft) {
//递归终止条件:访问空节点,最长路径为0
if(root==null) return 0;
//下面的叶子节点操作不需要
// if(root.left==null && root.right==null) return 1;
int left=0,right=0;
//下面不需要判断,判断会出错
// if(isLeft){//左
right=longestZigZag(root.right,false);
left=longestZigZag(root.left,true);
// }else{
// right=longestZigZag(root.right,true);
// left=longestZigZag(root.left,false);
// }
//本次递归所需要做的事:
//更新 当前根节点最大路径(左右子树路径长度较大者)
// 更新总体最大路径
int depth=Math.max(left,right);
max=Math.max(max,depth);
//当前节点的方向为向左,意味着上一步为向右,返回右子树的路径长度+1
return isLeft?right+1:left+1;//重要
}
}
/*class Solution {
int sum=0;
public:
void longest(TreeNode* root, int flag, int val)
{
if (!root) return ;
sum=max(sum,val);
if (flag)
{
longest(root->left, !flag, val+1);
longest(root->right, flag, 1);//重新置1
}
else
{
longest(root->right, !flag, val+1);
longest(root->left, flag, 1);
}
}
int longestZigZag(TreeNode* root) {
if (!root) return 0;
longest(root,true,0);
longest(root,false,0);
return sum;
}
};*/
路径总和112判断路径和是否等于一个数
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。
1.必须 从 根节点 到 叶子节点
2.前序遍历
public class 路径总和 {
public boolean hasPathSum(TreeNode root, int sum) {
//递归终止条件:访问到空节点
if(root==null) return false;
// 从根到叶子节点遍历
//通过减数 判断最后是否能为0
//前序遍历
//本次递归需要做的事情
//1.减去本节点的值
//2.判断本节点是否为叶子节点
//3.判断是否已经减到0
sum-=root.val;
// if(sum==0) return true;//不能直接判断,无法确保本节点为叶子节点
if(root.left==null&&root.right==null){//判断到达叶子节点
return sum==0;//判断是否减到0
}
//没有减到0
//进一步判断:左子树和右子树是否存在符合条件的路径
boolean left=hasPathSum(root.left,sum);
boolean right=hasPathSum(root.right,sum);
return left||right;
}
}
路径总和437统计路径和等于一个数的路径数量
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
1.区别于上一题:不一定从 根节点开始,不一定 到 叶子节点结束
2.全局变量
3.双重递归 思路:首先先序递归遍历每个节点,再以每个节点作为起始点递归寻找满足条件的路径。存在大量重复计算
public class 路径总和3 {
public int pathSum(TreeNode root, int sum) {
if(root==null) return 0;
int res=getPathSum(root,sum);
int left=pathSum(root.left,sum);
int right=pathSum(root.right,sum);
return res+left+right;
}
private int getPathSum(TreeNode root, int sum){
//递归终止条件
if(root==null) return 0;
//本轮递归所需要做的事
sum-=root.val;
int res=sum==0?1:0;
//返回当前根节点的路径和
return res+getPathSum(root.left,sum)+getPathSum(root.right,sum);
}
// int count;
// public int pathSum(TreeNode root, int sum) {
// if(root==null) return 0;
// getPathSum(root,sum);
// pathSum(root.left,sum);
// pathSum(root.right,sum);
// return count;
// }
// private void getPathSum(TreeNode root, int sum){
// if(root==null) return;
// sum-=root.val;
// if(sum==0){
// count++;
// // return count;
// }
// getPathSum(root.left, sum);
// getPathSum(root.right, sum);
// // return count;
// }
}
//优化
/*
所以第二种做法,采取了类似于数组的前n项和的思路,比如sum[4] == sum[1],那么1到4之间的和肯定为0
对于树的话,采取DFS加回溯,每次访问到一个节点,把该节点加入到当前的pathSum中
然后判断是否存在一个之前的前n项和,其值等于pathSum与sum之差
如果有,就说明现在的前n项和,减去之前的前n项和,等于sum,那么也就是说,这两个点之间的路径和,就是sum
最后要注意的是,记得回溯,把路径和弹出去
作者:a380922457
链接:https://leetcode-cn.com/problems/path-sum-iii/solution/liang-chong-fang-fa-jian-dan-yi-dong-ban-ben-by-a3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
class Solution {
public int pathSum(TreeNode root, int sum) {
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(0, 1);
return helper(root, map, sum, 0);
}
int helper(TreeNode root, HashMap<Integer, Integer> map, int sum, int pathSum){
int res = 0;
if(root == null) return 0;
pathSum += root.val;
res += map.getOrDefault(pathSum - sum, 0);
map.put(pathSum, map.getOrDefault(pathSum, 0) + 1);
res = helper(root.left, map, sum, pathSum) + helper(root.right, map, sum, pathSum) + res;
map.put(pathSum, map.get(pathSum) - 1);
return res;
}
}
//另一个回溯
/*
作者:ustcyyw
链接:https://leetcode-cn.com/problems/path-sum-iii/solution/437java-hui-su-da-bai-100-by-ustcyyw/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
private int count;
public int pathSum(TreeNode root, int sum) {
count = 0;
backTrack(root, sum, new int[1000], 0);
return count;
}
public void backTrack(TreeNode x, int sum, int[] pathItem, int curIndex){
if(x == null) return;
if(x.val == sum) count++;
for(int i = curIndex - 1, temp = x.val; i >= 0; i--){
temp += pathItem[i];
if(temp == sum)
count++;
}
pathItem[curIndex] = x.val;
backTrack(x.left, sum, pathItem, curIndex + 1);
backTrack(x.right, sum, pathItem, curIndex + 1);
}
二叉树的最小深度111
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。
1.根 到 叶子
//和最大相反
/*
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
return 1+Math.max(maxDepth(root.left), maxDepth(root.right));
}
*/
/*
求最小深度时将Math.max换成Math.min即可,
但要注意如果根节点的左或右子树为空的话是构不成子树的。
而最小深度是要求从根节点到子树的。
当左或右子树为空时,不符合要求。
*/
/*
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
// null节点不参与比较
if (root.left == null && root.right != null) {
return 1 + minDepth(root.right);
}
// null节点不参与比较
if (root.right == null && root.left != null) {
return 1 + minDepth(root.left);
}
return 1 + Math.min(minDepth(root.left), minDepth(root.right));
}
*/
public class 二叉树的最小深度 {
public int minDepth(TreeNode root) {
if(root==null) return 0;
return getMinDepth(root);
}
public int getMinDepth(TreeNode root){
//递归终止条件:访问到空节点
if(root==null) return 0;
if(root.left==null&&root.right==null) return 1;
if(root.left!=null&&root.right!=null){
int left=getMinDepth(root.left);
int right=getMinDepth(root.right);
return Math.min(left,right)+1;
}
if(root.left!=null){
return getMinDepth(root.left)+1;
}
if(root.right!=null){
return getMinDepth(root.right)+1;
}
return 0;
}
}
二叉树中的列表1367
给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表。
如果在二叉树中,存在一条一直向下的路径,且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值,那么请你返回 True ,否则返回 False 。
一直向下的路径的意思是:从树中某个节点开始,一直连续向下的路径。
1.起始不一定是 根节点
public class 二叉树中的列表 {
public boolean isSubPath(ListNode head, TreeNode root) {
// return dfs(head,root);//考虑不是必须从根节点开始
if(head==null) return true;//空链表 匹配
//因为下面要访问root的左右子树
//为了避免空指针
//添加判断root是否为空
if(root==null) return false;
// return dfs(head,root)||dfs(head,root.left)||dfs(head,root.right);
//重要:后面两个等于是换起始根节点(先往左子树dfs判断,再往右)
return dfs(head,root)||isSubPath(head,root.left)||isSubPath(head,root.right);
}
//以root为根节点的树与链表匹配的关键条件:
//1.当前root值与head值相等;2.左子树匹配3.右子树匹配
private boolean dfs(ListNode head, TreeNode root){
//递归终止条件:
//访问到链表的空节点 说明匹配成功
if(head==null) return true;//空链表 匹配
//访问到树的空节点 说明不匹配
if(root==null) return false;//空节点 不匹配
//本次递归需要做的事情:
//前序遍历
//当前树节点的值 与 当前链表节点的值 不等 ,返回不符合
if(head.val!=root.val) return false;
//判断
boolean left=dfs(head.next,root.left);
boolean right=dfs(head.next,root.right);
// if(head.next==null) return
//前面当前值已经相等,返回左右子树是否都匹配
return left||right;
}
}
检查子树 面试04.10
检查子树。你有两棵非常大的二叉树:T1,有几万个节点;T2,有几万个节点。设计一个算法,判断 T2 是否为 T1 的子树。
如果 T1 有这么一个节点 n,其子树与 T2 一模一样,则 T2 为 T1 的子树,也就是说,从节点 n 处把树砍断,得到的树与 T2 完全相同。
1.从上一题1367 -----链表改树,完全一致
class 检查子树 {
public boolean checkSubTree(TreeNode t1, TreeNode t2) {
if(t2==null) return true;
if(t1==null) return false;
return check(t1,t2)||checkSubTree(t1.left,t2)||checkSubTree(t1.right,t2);
}
private boolean check(TreeNode t1, TreeNode t2){
if(t2==null) return true;
if(t1==null) return false;
if(t2.val!=t1.val) return false;
return check(t1.left,t2.left)||check(t1.right,t2.right);
}
}
另一个树的子树572
给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。
s 的一个子树包括 s 的一个节点和这个节点的所有子孙。
s 也可以看做它自身的一棵子树。
1.和前两题有边界差异
class 另一个树的子树 {
public boolean isSubtree(TreeNode s, TreeNode t) {
// if(t==null) return true;
// if(s==null) return false;
if (t == null || s == null) return false;
return isSub(s,t)||isSubtree(s.left,t)||isSubtree(s.right,t);
}
private boolean isSub(TreeNode s, TreeNode t){
//注释的边界错误
// if(t==null) return true;
// if(s==null) return false;
if (t == null && s == null) return true;
if (t == null || s == null) return false;
if(s.val!=t.val) return false;
boolean left=isSub(s.left,t.left);
boolean right=isSub(s.right,t.right);
return left&&right;
}
}
翻转二叉树226
public class 翻转二叉树 {
public TreeNode invertTree(TreeNode root) {
//递归终止条件 空节点
if(root==null) return null;
//前序遍历
//翻转后的左右子树
TreeNode left=invertTree(root.left);
TreeNode right=invertTree(root.right);
//本轮递归操作
//1.根节点左节点换为原来的右子树
root.left=right;
//2.根节点右节点换为原来的左子树
root.right=left;
//返回根节点
return root;
}
}
合并二叉树617
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。
合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,
否则不为 NULL 的节点将直接作为新二叉树的节点。
public class 合并二叉树 {
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
//递归终止条件
if(t1==null) return t2;
if(t2==null) return t1;
//返回合并后的左右子树
TreeNode left=mergeTrees(t1.left,t2.left);
TreeNode right=mergeTrees(t1.right,t2.right);
//本次递归操作
//根节点值更新为 求和
TreeNode root=new TreeNode(t1.val+t2.val);
//将左右子树分别接到根节点
root.left=left;
root.right=right;
// t1.left.val+=t2.left.val;
// t1.right.val+=t2.left.val;
return root;
}
}
对称二叉树101
//递归
public class 对称二叉树 {
public boolean isSymmetric(TreeNode root) {
if(root==null) return true;
boolean res=isSymmetric(root,root);
return res;
}
private boolean isSymmetric(TreeNode leftNode,TreeNode rightNode){
//递归终止:同时遍历到空节点 对称
if(leftNode==null&&rightNode==null) return true;
//只有一个遍历到了空 不对称
if(leftNode==null||rightNode==null) return false;
//本地递归操作:
//判断当前节点左右子节点值相等 且左右子树对称
return leftNode.val==rightNode.val&&isSymmetric(leftNode.left,rightNode.right)&&isSymmetric(leftNode.right,rightNode.left);
}
}
//迭代
class Solution {
public boolean isSymmetric(TreeNode root) {
return check(root,root);
}
private boolean check(TreeNode leftNode,TreeNode rightNode){
Queue<TreeNode> que=new LinkedList<>();
que.offer(leftNode);
que.offer(rightNode);
while(!que.isEmpty()){
leftNode=que.poll();
rightNode=que.poll();
if(leftNode==null&&rightNode==null) return true;
if(leftNode==null||rightNode==null||leftNode.val!=rightNode.val) return false;
que.offer(leftNode.left);
que.offer(rightNode.right);
que.offer(leftNode.right);
que.offer(rightNode.left);
}
return true;
}
}
左叶子之和404
class 左叶子之和 {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null) return 0;
int res = 0;
//判断节点是否是左叶子节点,如果是则将它的和累计起来
if(root.left != null && root.left.left == null && root.left.right == null){
res += root.left.val;//res = root.left.val;
}
return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right) + res;
}
}
/*public int sumOfLeftLeaves(TreeNode root) {
if(root==null) return 0;
return sumOfLeftLeaves(root.left,true)+sumOfLeftLeaves(root.right,false);
}
public int sumOfLeftLeaves(TreeNode root,boolean isLeftLeaves){
//递归终止条件:空节点 和为0
if(root==null) return 0;
int leaves=0;
//判断为左叶子
if(isLeftLeaves&&root.left==null&&root.right==null){//只判断了叶子节点,没判断左叶子
leaves=root.val;
};
//左右子树的左叶子之和
int left=sumOfLeftLeaves(root.left,true);//
int right=sumOfLeftLeaves(root.right,false);
return leaves+left+right;
}*/
最大二叉树654
给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:
二叉树的根是数组中的最大元素。
左子树是通过数组中最大值左边部分构造出的最大二叉树。
右子树是通过数组中最大值右边部分构造出的最大二叉树。
通过给定的数组构建最大二叉树,并且输出这个树的根节点。
public class 最大二叉树 {
public TreeNode constructMaximumBinaryTree(int[] nums) {
if(nums==null||nums.length==0)
return null;
//递归终止条件
//nums中数字都取了以后
TreeNode root=constructMaximum(nums,0,nums.length-1);
return root;
}
public int findMax(int[] nums,int i,int j){
// int index=i;
int max=nums[i],index=i;
for(int t=i;t<=j;t++){
if(nums[t]>max){
index=t;
max=nums[t];
}
}
return index;//返回[i,j]之间最大值的索引
}
public TreeNode constructMaximum(int[] nums,int i,int j) {
// if(nums==null||nums.length==0)
// return null;
//递归终止条件
if(i>j) return null;
//nums中数字都取了以后
// int i=0,j=nums.length-1;
int mid=findMax(nums,i,j);
TreeNode root=new TreeNode(nums[mid]);
// TreeNode left=null,right=null;错误
//左子树最大值
//可以不判断mid左右边是否有数
//第一步边界判断了 i>j则返回null
root.left=constructMaximum(nums,i,mid-1);//左边界不变 不可以设为0
root.right=constructMaximum(nums,mid+1,j);//右边界不变 不可以设为最后一个
// if(mid>0){
// root.left=constructMaximum(nums,i,mid-1);
// }
// if(mid<nums.length-1){
// root.right=constructMaximum(nums,mid+1,j);
// }
// root.left=left;错误
// root.right=right;错误
return root;
}
}
二叉树中第二小的节点671
给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。
如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个。
给出这样的一个二叉树,你需要输出所有节点中的第二小的值。如果第二小的值不存在的话,输出 -1 。
public int findSecondMinimumValue(TreeNode root) {
return myfun(root, root.val);
}
public int myfun(TreeNode root, int val) {
if (root == null) {
return -1;
}
if (root.val > val) {
return root.val;
}
int l = myfun(root.left, val);
int r = myfun(root.right, val);
if (l > val && r > val) {
return Math.min(l,r);
}
return Math.max(l,r);
}
//方法2
public class 二叉树中第二小的节点 {
public int findSecondMinimumValue(TreeNode root) {
//一个节点要么具有 0 个或 2 个子节点,如果有子节点,那么根节点是最小的节点。
//递归终止条件:空节点 返回-1
if (root == null) return -1;
//只有一个节点 叶子节点 返回-1
if (root.left == null && root.right == null) return -1;
//存在两个叶子节点
//本次递归需要做的事:
int leftVal = root.left.val;
int rightVal = root.right.val;
//左节点较小 右节点比根节点大 ----找左子树第二小
if (leftVal == root.val) leftVal = findSecondMinimumValue(root.left);
//右节点较小 左节点比根节点大 ----找右子树第二小
if (rightVal == root.val) rightVal = findSecondMinimumValue(root.right);
//左子树右子树均存在 返回两者最小
if (leftVal != -1 && rightVal != -1) return Math.min(leftVal, rightVal);
//只有左子树存在 返回左边
if (leftVal != -1) return leftVal;
//只有右子树存在 返回右边
return rightVal;
}
}
打家劫舍3 337