算法-二叉樹路徑問題

二叉樹的路徑問題一般可以用DFS搜索來解決,遞歸的思想一定要理解(注重最後一步和終止條件)

1、判斷二叉樹中是不是有給定和的路徑

	//
    public boolean hasPathSum(TreeNode root, int sum) {
        if(root==null){
            return false;
        }
        sum-=root.val;
        if(sum==0&&root.left==null&&root.right==null){//終止條件
            return true;
        }
        //找一下左右子樹
        return hasPathSum(root.left,sum)||hasPathSum(root.right,sum);
    }

2、找出二叉樹中給定和的所有路徑

    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> list=new ArrayList<>();
        dfs(list,new ArrayList<>(),root,sum);
        return list;
    }

    public void dfs(List<List<Integer>> list,List<Integer> path,TreeNode root,int sum){
        if(root==null){
            return;
        }
        sum-=root.val;
        path.add(root.val);
        //終止條件
        if(sum==0&&root.left==null&&root.right==null){
            list.add(new ArrayList<>(path));
        }else{
        	//搜索左右子樹
            dfs(list,path,root.left,sum);
            dfs(list,path,root.right,sum);
        }
        path.remove(path.size()-1);
        
    }

3、二叉樹中的所有路徑

    public List<String> binaryTreePaths(TreeNode root) {
        List<String> list=new ArrayList<>();
        dfs(list,"",root);
        return list;
    }

    public void dfs(List<String> list,String path,TreeNode node){
        if(node==null){
            return;
        }
        String temp="";
        if(path.length()==0){
            temp=""+node.val;
        }else{
            temp=path+"->"+node.val;
        }
        if(node.left==null&&node.right==null){
            list.add(temp);
        }else{
            dfs(list,temp,node.left);
            dfs(list,temp,node.right);
        }
    }

4、二叉樹中最大路徑和

124. 二叉樹中的最大路徑和 Hard難度。

給定一個非空二叉樹,返回其最大路徑和。

本題中,路徑被定義爲一條從樹中任意節點出發,達到任意節點的序列。該路徑至少包含一個節點,且不一定經過根節點。

示例 1:

輸入: [1,2,3]

       1
      / \
     2   3

輸出: 6
示例 2:

輸入: [-10,9,20,null,null,15,7]

   -10
   / \
  9  20
    /  \
   15   7

輸出: 42

本例中需要注意的就是有可能不經過根節點,但我們知道,這條路徑必然會經過一個節點

所以我們在經過每個節點的時候計算最大路徑值,更新現有的最大路徑值

max=Math.max(max,leftSum+rightSum+node.val);//經過當前節點的最大路徑和

然後返回經過本節點的一個較大分支

return node.val+Math.max(leftSum,rightSum);//經過該節點的一支較大的路徑

左子樹最大路徑和爲

int leftSum=Math.max(0,helper(node.left));
    public int maxPathSum(TreeNode root) {
        helper(root);
        return max;
    }
    private int max=Integer.MIN_VALUE;
    private int helper(TreeNode node){
        if(node==null){
            return 0;
        }
        int leftSum=Math.max(0,helper(node.left));
        int rightSum=Math.max(0,helper(node.right));
        max=Math.max(max,leftSum+rightSum+node.val);//經過當前節點的最大路徑和
        return node.val+Math.max(leftSum,rightSum);//經過該節點的一支較大的路徑
    }

5、二叉樹的最大直徑

543. 二叉樹的直徑

給定一棵二叉樹,你需要計算它的直徑長度。一棵二叉樹的直徑長度是任意兩個結點路徑長度中的最大值。這條路徑可能穿過也可能不穿過根結點。

示例 :
給定二叉樹

          1
         / \
        2   3
       / \     
      4   5    
返回 3, 它的長度是路徑 [4,2,1,3] 或者 [5,2,1,3]。
注意:兩結點之間的路徑長度是以它們之間邊的數目表示。

這個題其實也很容易理解,就是某個節點的左子樹深度+右子樹深度,就是他的直徑。
明白了這一點,我們再想一想我們是如何求二叉樹深度的?

public int getDepth(TreeNode node){
	if(node==null){
		return 0;
	}
	return 1+Math.max(getDepth(node.left),getDepth(node.right));
}

現在我們對其改造一下,改造的點就是我們對每個點的左右子樹進行判斷,而不僅僅是根節點的左右子樹。左右子樹的高度和就是直徑

    int max=0;
    public int getDepth(TreeNode root) {
        depth(root);
        return max;
    }
    public int depth(TreeNode node){
        if(node==null){
            return 0;
        }
        int leftDepth=depth(node.left);
        int rightDepth=depth(node.right);
        int temp=leftDepth+rightDepth;
        max=Math.max(max,temp);
        return Math.max(leftDepth,rightDepth)+1;
    }
}

6、二叉樹的最小深度

和最大深度很相似,不過要分左子樹和右子樹中有一個爲null的情況。

    public int minDepth(TreeNode root) {
        if(root==null){
            return 0;
        }
        if((root.left==null&&root.right!=null)||(root.left!=null&&root.right==null)){
            return root.left==null?1+minDepth(root.right):1+minDepth(root.left);
        }
        return 1+Math.min(minDepth(root.left),minDepth(root.right));
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章