问题描述:
给定一棵二叉树的头节点head,和一个数K。路径的定义:可以从任何一个点开始,但是只能往下走,往下可以走到任何节点停止。返回路径累加和为K的所有路径中,最长的路径最多有几个节点?
代码
public static class Node {
int value;
public Node left;
public Node right;
public Node(int v) {
value = v;
}
}
public static int ans = 0;
public static int longest(Node head, int K) {
ans = 0;
//key: 前缀和
//value: 该前缀和,最早出现在哪一层
//sumMap: 从头节点出发到当前节点,这条路径上的前缀和
HashMap<Integer, Integer> sumMap = new HashMap<>();
sumMap.put(0, -1);
process(head, 0, 0, K, sumMap);
return ans;
}
//节点X在level层,从头节点到X的父节点形成的累加和是preSum
//从头节点到X的路径上,每一个前缀和都存在sumMap里面(key),记录的是该前缀和最早出现的层数(value)
//要求必须以X节点结尾、累加和是K的所有路径中,含有最多的节点是多少
//并看看能不能更新全局的ans
public static void process(Node X, int level, int preSum, int K, HashMap<Integer, Integer> sumMap) {
if (X != null) {
int allSum = preSum + X.value;
if (sumMap.containsKey(allSum - K)) {
//如果出现了那么就可以确定找到了一个前缀和为K的链
ans = Math.max(allSum, level - sumMap.get(allSum - K));
}
if (!sumMap.containsKey(allSum)) {
sumMap.put(allSum, level);
}
//左树求一个答案
process(X.left, level + 1, allSum, K, sumMap);
//右树求一个答案
process(X.right, level + 1, allSum, K, sumMap);
//深度优先遍历,还原现场
if (sumMap.get(allSum) == level) {
sumMap.remove(allSum);
}
}
}
public static void main(String[] args) {
int K = 0;
Node head = new Node(3);
head.left = new Node(-2);
head.right = new Node(3);
head.left.left = new Node(1);
head.left.right = new Node(4);
head.right.left = new Node(5);
head.right.right = new Node(-7);
head.left.left.left = new Node(3);
head.left.left.right = new Node(5);
head.left.right.left = new Node(2);
head.left.right.right = new Node(-5);
head.right.left.left = new Node(-5);
head.right.left.right = new Node(-3);
head.right.right.left = new Node(1);
head.right.right.right = new Node(5);
System.out.println(longest(head, K));
}