- 写递归的技巧
我的一点心得是:明白一个函数的作用
并相信它能完成这个任务
,千万不要试图跳进细节。千万不要跳进这个函数里面企图探究更多细节,否则就会陷入无穷的细节无法自拔,人脑能压几个栈啊。
二叉树最大深度
遍历游走–没有返回结果–有全局变量—需要两个函数
private int max;//全局变量在外 不给值
public int maxDepth(TreeNode root) {
max=0;
core(root,1);
return max;
}
public void core(TreeNode root,int depth)
{
if(root==null){return ;}
max=Math.max(max,depth);
core(root.left,depth+1);
core(root.right,depth+1);
}
分治法–有返回结果—逻辑在最后那个return,计算结果的时候顺便把逻辑写里面,前面就是不管任何的鲁棒/出口之后,直接调用函数返回你想要的值,最后丢给结果去逻辑
public int maxDepth(TreeNode root) {
// 出口
if(root==null){return 0;}
int left=maxDepth(root.left);
int right=maxDepth(root.right);
//递归
return Math.max(left,right)+1;
}
public class Solution {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
return getMin(root);
}
public int getMin(TreeNode root){
//出口
if (root == null) {
return Integer.MAX_VALUE;
}
//逻辑
if (root.left == null && root.right == null) {
return 1;
}
//逻辑+结果
return Math.min(getMin(root.left), getMin(root.right)) + 1;
}
}
public int minDepth(TreeNode root) {
//鲁棒出口
if (root == null) return 0;
//逻辑+结果
if (root.left == null) return minDepth(root.right) + 1;
if (root.right == null) return minDepth(root.left) + 1;
return Math.min(minDepth(root.left), minDepth(root.right)) + 1;
/*找到叶子节点结束 只要结点还有左右结点他就不是叶子节点
left为空去看right right即使为空了 是叶子节点0+1也加上了遍历到的叶子节点
left不空 right空 说明还不是叶子节点 那就让结果变为left的结果 比较都是left值
最后都不空 真的比较两个不同的值
*/
}
//同时思考深度和是否平衡
class ResultType {
public boolean isBalanced;
public int maxDepth;
public ResultType(boolean isBalanced, int maxDepth) {
this.isBalanced = isBalanced;
this.maxDepth = maxDepth;
}
}
public class Solution {
public boolean isBalanced(TreeNode root) {
return helper(root).isBalanced;
}
private ResultType helper(TreeNode root) {
//鲁棒 出口
if (root == null) {
return new ResultType(true, 0);
}
//逻辑
ResultType left = helper(root.left);
ResultType right = helper(root.right);
//结果
// subtree not balance
if (!left.isBalanced || !right.isBalanced) {
return new ResultType(false, -1);
}
// root not balance
if (Math.abs(left.maxDepth - right.maxDepth) > 1) {
return new ResultType(false, -1);
}
return new ResultType(true, Math.max(left.maxDepth, right.maxDepth) + 1);
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { //逻辑
if(root==null){return null;}//很节点为空直接返回空/到叶子节点也返回空
if(root==p||root==q){return root;}//如果p.q中有是Root的祖先一定是root
//递归
TreeNode left=lowestCommonAncestor(root.left,p,q);
TreeNode right=lowestCommonAncestor(root.right,p,q);
//结果
if(left!=null&&right!=null){return root;}//左右都找到了祖先那就是root
if(left!=null){return left;}//左子树找到了祖先
if(right!=null){return right;}//右子树找到了祖先
return null;//找不到祖先
}
二叉树,找到根节点出发到任意结点结束 的 最大路径和
root->leaf
public int maxSum(TreeNode root)
{
if(root==null){return 0;}
int left=maxSum(root.left);
int right=maxSum(root.right);
//递归+结果
return Math.max(left,right)+root.val;
}
root->any
如果当前的路径和已经比0还小我们就不会要它,直接丢弃,清空为0
public int maxSum(TreeNode root)
{
if(root==null){return 0;}
int left=maxSum(root.left);
int right=maxSum(root.right);
//递归+结果
return Math.max(0,Math.max(left,right))+root.val;
}
any->any
情况1:根节点 右子树 如果负数很多 最大路径只在左子树
情况2:最大路径只在右子树
情况3:最大路径横跨左右子树,
先在左子树中 求左子树的根节点到任意节点的最大路径和
右子树中求 右子树的根节点到任意结点的最大路径和
最后把上面两个路径和相加再加上根节点的值 就是整体最大
根据以上分析 前两种情况 要先求左右子树的root2Any(root->any )并且最大值作为本轮的any2ANy
第三种情况:=左右子树谁的any->any路径和大 就 去和左+右+根比较
因为any2Any是我们要求的,但是root2Any是我们依赖的,有多个因素影响我们的结果,所以要写一个结果类型,和上面平衡二叉树,需要求高度的同时要求是否平衡一样
class ResultType
{
int root2Any;
int any2Any;
public ResultType(int a,int b){this.root2Any=a; this.any2Any=b;}
}
public class Solution
{
public int maxSum(TreeNode root)
{
ResultType result=helper(root);
return result.any2Any;
}
private ResultType helper(TreeNode root)
{
if(root==null)
{
return new ResultType(Intger.MIN_VALUE,Intger.MIN_VALUE);
}
//分
ResultType left=helper(root.left);
ResultType right=helper(root.right);
//治
int root2Any=Math.max(0,Math.max(left.root2Any,right.root2Any))+root.val;
int any2Any=Math.max(left.any2Any,right.any2Any);//最大路径完全在左边或这右边
any2Any=Math.max(any2Any,Math.max(0,left.root2Any)+Math.max(0,right.root2Any)+root.val);//第三种情况 左+root+右
return new ResultType(root2Any,any2Any);
}
}
BST 二叉搜索树/二叉排序树
binary seratch/sorted tree
左子树《=根
右子树》根
左子树《根
右子树》=根
中序遍历是一个升序序列
层遍历的DFS实现方法