1. 程式人生 > >LeetCode437. Path Sum III

LeetCode437. Path Sum III

437. Path Sum III

You are given a binary tree in which each node contains an integer value.

Find the number of paths that sum to a given value.

The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).

The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.

Example:

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

      10
     /  \
    5   -3
   / \    \
  3   2   11
 / \   \
3  -2   1

Return 3. The paths that sum to 8 are:

1.  5 -> 3
2.  5 -> 2 -> 1
3. -3 -> 11

計算二叉樹中從上到下的路徑中和為目標值的個數。路徑的起點可以是子樹的根結點,終點可以不是葉子結點,但一定是自上而下的。

helper函式用於計算從root到各個葉子結點路徑上和為目標值的個數,這個和

https://blog.csdn.net/grllery/article/details/85253178類似。不同的地方在於pathSum中計算的方式。因為二叉樹的特性,因此將根結點改為左右結點,分別呼叫pathSum函式,從而更改了helper函式的中的搜尋起點,類似於暴力搜尋。

程式碼見:https://github.com/abesft/leetcode/blob/master/437PathSumIII/437PathSumIII.cpp

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

//https://leetcode.com/problems/path-sum-iii/discuss/91889/Simple-Java-DFS
class Solution {
public:
	int pathSum(TreeNode* root, int sum) {
		if (root == nullptr)
			return 0;
		int ans = 0;
		helper(root, ans, sum);
		return ans + pathSum(root->left, sum) + pathSum(root->right, sum);
	}

private:
	void helper(TreeNode* root, int &ans, int remain) {
		if (root == nullptr)
			return;

		remain -= root->val;
		if (remain == 0)
			ans++;

		helper(root->left, ans, remain);
		helper(root->right, ans, remain);
	}
};

第二種方法是用hash表記錄前面已經出現過的和以及次數,然後查詢hash表中是否存在 current_sum - target_sum 這個鍵值。具體分析見https://blog.csdn.net/grllery/article/details/85332237

#include <iostream>
#include<unordered_map>
using namespace std;


//https://leetcode.com/problems/path-sum-iii/discuss/91878/17-ms-O(n)-java-Prefix-sum-method
class Solution2 {
public:
	int pathSum(TreeNode* root, int sum) {
		int res = 0;
		//key:前i個元素的和,value:對應和的個數
		unordered_map<int, int> sum_counts;
		int current_sum = 0;
		sum_counts[current_sum]++;
		preSum(root, sum_counts, current_sum, sum, res);
		return res;
	}

private:
	void preSum(TreeNode* root, unordered_map<int, int>& sum_counts, int& current_sum, int& target_sum, int& res) {
		if (root == nullptr)
			return;

		current_sum += root->val;
		auto iter = sum_counts.find(current_sum - target_sum);
		if (iter != sum_counts.end())
			res += iter->second;

		sum_counts[current_sum]++;

		preSum(root->left, sum_counts, current_sum, target_sum, res);
		preSum(root->right, sum_counts, current_sum, target_sum, res);

		sum_counts[current_sum]--;
		current_sum -= root->val;
	}
};