【二叉树-最长路径系列(任意路径)】直径、最长同值路径、 最大路径和(DFS、树形DP)

总述

  • 这类题目都是求一个最长路径,这个路径可以不经过根节点。
  • 使用dfs(即递归地遍历树)的方法。维护一个全局最长路径max作为最终结果,而递归方法dfs返回的是含根节点的最长路径。(若不使用全局变量,也可将返回类型构造自定义类,如题目124的代码2)
  • 注意题目是求路径(两点之间一条线)与节点数的区别,
    • 决定+1之类的细节
    • 决定dfs的递归终止是null节点还是叶子结点(若是叶子结点,当到叶子结点,要控制不进入null结点)。
  • 另外,求不经过根节点的最长路径一定是全部节点都要遍历,不存在剪枝情况,所以dfs不要放到if语句中。
  • 另附树形DP的思想:满足"依次求出每一个节点为根节点的二叉树的子树上的最大距离,那么最终答案一定在其中",所以可以使用树形dp。
    详细分析步骤按树形dp步骤来即可,简单。

题目 543. 二叉树的直径

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过根结点。

代码

class Solution {
    private int maxLen=0;
    public int diameterOfBinaryTree(TreeNode root) {
        if(root==null){return 0;}
        getTreeHeight(root);
        return maxLen;
    }

    private int getTreeHeight(TreeNode root){
        if(root.left==null&&root.right==null){
            return 0;
        }

        int leftHeight=root.left==null?0:getTreeHeight(root.left)+1;
        int rightHeight=root.right==null?0:getTreeHeight(root.right)+1;
        maxLen=Math.max(maxLen,leftHeight+rightHeight);
        return Math.max(leftHeight,rightHeight);
    }
}

题目 687. 最长同值路径

给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。

注意:两个节点之间的路径长度由它们之间的边数表示。

题解

增加判断,若左孩子与当前节点值不同,则清左边最大同值路径长度=0;右孩子同理。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private int maxLen=0;
    public int longestUnivaluePath(TreeNode root) {
        if(root==null){return 0;}
        dfs(root);
        return maxLen;
    }

    private int dfs(TreeNode root){
        if(root.left==null&&root.right==null){
            return 0;
        }

        int leftMaxLen=root.left==null?0:dfs(root.left)+1;//因为所有路径都要遍历到,所以不能有剪枝操作,所以dfs不能放到if里面去。
        if(root.left!=null&&root.left.val!=root.val){
            leftMaxLen=0;
        }
        int rightMaxLen=root.right==null?0:dfs(root.right)+1;
        if(root.right!=null&&root.right.val!=root.val){
            rightMaxLen=0;
        }

        maxLen=Math.max(maxLen,leftMaxLen+rightMaxLen);
        return Math.max(leftMaxLen,rightMaxLen);
    }
}

题目 124. 二叉树中的最大路径和

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

题解

与上两题不同,这题是求节点和,所以当和为负,要更新为0;

代码

class Solution {
	private int max = Integer.MIN_VALUE;

	public int maxPathSum(TreeNode root) {
		maxRootPathSum(root);
		return max;
	}

    private int maxRootPathSum(TreeNode root){
        if(root==null){return 0;}

        int leftMaxVal=Math.max(0,maxRootPathSum(root.left));
        int rightMaxVal=Math.max(0,maxRootPathSum(root.right));
        max=Math.max(max,leftMaxVal+rightMaxVal+root.val);
        return Math.max(leftMaxVal,rightMaxVal)+root.val;
    }
}

代码2 返回类型使用构造类,代替类变量

class Type{
	int maxDis;
	int treeHeight;
	
	public Type(int maxDis,int treeHeight) {
		this.maxDis=maxDis;
		this.treeHeight=treeHeight;
	}
}

public class Main {	
	public static void main(String args[]) {
		//test
		Node n1=new Node(1);
		Node n2=new Node(2);
		Node n3=new Node(3);
		Node n4=new Node(4);
		Node n5=new Node(5);
		n1.left=n2;
		n1.right=n3;
		n3.left=n4;
		n3.right=n5;
		
		int maxDis=maxDistance(n1).maxDis;
		System.out.println(maxDis);
	}
	
	public static Type maxDistance(Node root) {
		if(root==null) {
			return new Type(0,0);
		}
		Type lMes=maxDistance(root.left);
		Type rMes=maxDistance(root.right);
		int disTemp=lMes.treeHeight+rMes.treeHeight+1;
		int maxDis=Math.max(Math.max(lMes.maxDis, rMes.maxDis), disTemp);
		int height=Math.max(lMes.treeHeight, rMes.treeHeight)+1;
		return new Type(maxDis,height);
	}
}
原文地址:https://www.cnblogs.com/coding-gaga/p/11318622.html