1. 程式人生 > >[leetcode]樹求和的一些題

[leetcode]樹求和的一些題

1.sum-root-to-leaf-numbers

題目描述:
Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.An example is the root-to-leaf path 1->2->3 which represents the number 123.Find the total sum of all root-to-leaf numbers.

For example,
    1
   /  \
  2   3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Return the sum = 12 + 13 =25.

思路:
深度優先的先序遍歷,遍歷到一個節點時,計算出一個新的value,若該節點是葉子節點,則把這個value加到最終的結果上,否則帶著這個值去遍歷其左子樹和右子樹。

程式碼:

public class Solution {
    int sum=0;
    public int sumNumbers(TreeNode root) {
        if(root==null){
            return 0;
        }
        getNumber(root,0);
        return sum;
    }
    
    public void getNumber(TreeNode root,int value){
        value=value*10+root.val;				//遍歷到某一節點,value值的更新
        if(root.left==null&&root.right==null){
            sum=sum+value;
        }
        if(root.left!=null){
            getNumber(root.left,value);
        }
        if(root.right!=null){
            getNumber(root.right,value);
        }
    }
}

更為優雅的思路:
僅採用遞迴的思想,遍歷到某一點時,把該點更新的value值傳遞給其左子樹和右子樹,遞迴結束的條件是,若遍歷到一個節點是葉子節點時,則返回其更新的valve值,供父節點歸併結果使用。

更為優雅的程式碼:

public int sumNumbers(TreeNode root) {
    return helper(root,0);
}
private int helper(TreeNode root, int sum)
{
    if(root == null)
        return 0;
    if(root.left==null && root.right==null)
        return sum*10+root.val;
    return helper(root.left,sum*10+root.val)+helper(root.right,sum*10+root.val);
}

2.binary-tree-maximum-path-sum

題目描述:
Given a binary tree, find the maximum path sum.The path may start and end at any node in the tree.

For example:
Given the below binary tree,
       1
      /  \
     2   3
Return 6.

思路:
先定義一個ArrayList型別的result,result的第0個位置存放當前的最大值,result會不斷的被更新。遞迴求得最大值。
每訪問到一個節點的時候,需要遞迴計算出其左子樹的最大路徑和右子樹的最大路徑,然後加上此節點的val(這裡還需要將其左子樹的最大路徑和右子樹的最大路徑與零相比,只有大於零才與該節點的val值加和,用於更新判斷),得到以此節點為根節點的路徑值,判斷該值是否大於當前的最大值,若大於則把結果放到result的第0位。
遞迴結束是當一個節點為空節點時,返回路徑0;否則,計算過以該節點為根節點的路徑值吼,返回左/右路徑值和0中較大的值和此節點val的加和。因為若該節點不是根節點時,最終的結果只能是走其左子樹或走其右子樹。

程式碼:

public class Solution {
    public int maxPathSum(TreeNode root) {
        if(root==null){
            return 0;
        }
        ArrayList<Integer> result=new ArrayList<Integer>();
        result.add(Integer.MIN_VALUE);
        backtrace(root,result);
        return result.get(0);
    }
    public int backtrace(TreeNode root,ArrayList<Integer> result){
        if(root==null)
            return 0;
        int left=backtrace(root.left,result);
        int right=backtrace(root.right,result);
        int cur=root.val+Math.max(left,0)+Math.max(right,0);
        if(cur>result.get(0)){
            result.add(0,cur);
        }
        return root.val+Math.max(left,Math.max(right,0));
    }
}

3.path-sum

題目描述:
Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.

For example:
Given the below binary tree and sum = 22,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \      \
        7    2      1
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.

思路:
深度優先遍歷,當遍歷到一個節點時,若該節點是葉子節點,則判斷該節點的val值和當前給定的sum值是否相等,若相等,則返回true;否則,用現有的sum值減去本身的val值,傳遞給其左子樹和右子樹,遞迴呼叫這個函式,但凡左右子樹有一個路徑和等於傳遞來的值,即返回true,即 return left||right。

程式碼:

public class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
        if(root!=null&&root.left==null&&root.right==null&&root.val==sum){
            return true;
        }
        boolean left=false;
        boolean right=false;
        if(root!=null&&root.left!=null){
            left=hasPathSum(root.left,sum-root.val);
        }
        if(root!=null&&root.right!=null){
            right=hasPathSum(root.right,sum-root.val);
        }
        return left||right;
    }
}

4.path-sum ii

題目描述:
Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.

For example:
Given the below binary tree and sum = 22,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1
        
return:
[
   [5,4,11,2],
   [5,8,4,5]
]

思路:
同3一樣,但需要一個arraylist來儲存現有的路徑,深度優先遍歷該樹,訪問到一個節點時,若該節點是葉子節點,則需判斷該節點的val值和給定的sum值是否相等,若相等,則把該葉子節點新增到arraylist中,並把該arraylist新增到最終結果result中。若遍歷的點不是葉子節點,則需要先把該值新增到arraylist中,若其左/右子樹不為空,則new一個新的list,把arraylist傳遞給該list,並更新sum值為當前sum值減去該節點的val值,遞迴呼叫該函式。最終返回結果result即可。

程式碼:

public class Solution {
    public ArrayList<ArrayList<Integer>> result=new ArrayList<ArrayList<Integer>>();
    public ArrayList<ArrayList<Integer>> pathSum(TreeNode root, int sum) {
        if(root==null){
            return result;
        }
        ArrayList<Integer> rowResult=new ArrayList<Integer>();
        getAnswer(rowResult,root,sum);
        return result;
    }
    public void getAnswer(ArrayList<Integer> rowResult,TreeNode root, int sum){
        if(root.left==null&&root.right==null){
            if(root.val==sum){
                rowResult.add(root.val);
                result.add(rowResult);
            }
            return;
        }
        rowResult.add(root.val);
        int value=sum-root.val;
        if(root.left!=null){
            ArrayList<Integer> leftResult=new ArrayList<Integer>(rowResult);
            getAnswer(leftResult,root.left,value);
            //rowResult.remove(rowResult.size()-1);
        }
        if(root.right!=null){
            ArrayList<Integer> rightResult=new ArrayList<Integer>(rowResult);
            getAnswer(rightResult,root.right,value);
        }
        
    }
}