1、思路
-
前序遍历的同时计算从根节点到当前节点路径之和,哈希表的键表示路径前缀和,值表示路径终点所在的层(因为路径只能由上自下);
-
遍历过程中若在哈希表中找到
curSum - targetSum
,则表示已经找到一条累加和为指定值的路径,更新其路径长度; -
哈希表初始化
hash[0] = 0
,表示第0
层的路径和为0
。
2、代码
#include <iostream>
#include <unordered_map>
using namespace std;
struct TreeNode
{
int val;
TreeNode *left, *right;
TreeNode(int _val) : val(_val), left(nullptr), right(nullptr) {}
};
void createTree(TreeNode *root, int &n) //建树
{
if (n == 0) return;
int fa, left, right, val;
cin >> fa >> left >> right >> val;
root->val = val;
if (left != 0)
{
root->left = new TreeNode(left);
createTree(root->left, -- n);
}
if (right != 0)
{
root->right = new TreeNode(right);
createTree(root->right, -- n);
}
}
int preOrder(TreeNode *root, int targetSum, int preSum, int level, int maxLen,
unordered_map<int, int> &hash)
{
if (root == nullptr) return maxLen;
int curSum = preSum + root->val;
//若上层已有相同的curSum,则不更新,因为用上层的会使路径更长
if (hash.find(curSum) == hash.end())
{
hash[curSum] = level; //将当前层的curSum加入到哈希表中
}
if (hash.find(curSum - targetSum) != hash.end())
{
maxLen = max(maxLen, level - hash[curSum - targetSum]);
}
//继续遍历左右子树
maxLen = max(preOrder(root->left, targetSum, curSum, level + 1, maxLen, hash),
preOrder(root->right, targetSum, curSum, level + 1, maxLen, hash));
if (hash[curSum] == level) //回溯到上一层时,把当前层的curSum移除
{
hash.erase(curSum);
}
return maxLen;
}
int main()
{
int n, fa;
cin >> n >> fa;
TreeNode *root = new TreeNode(0);
createTree(root, n);
int targetSum;
cin >> targetSum;
unordered_map<int, int> hash;
hash[0] = 0;
cout << preOrder(root, targetSum, 0, 1, 0, hash) << endl;
return 0;
}