0
点赞
收藏
分享

微信扫一扫

程序员代码面试指南第二版 37.在二叉树中找到累加和为指定值的最长路径长度


​​welcome to my blog​​

程序员代码面试指南第二版 37.在二叉树中找到累加和为指定值的最长路径长度

题目描述

给定一颗二叉树和一个整数 sum,求累加和为 sum 的最长路径长度。路径是指从某个节点往下,每次最多选择一个孩子节点或者不选所形成的节点链。

输入描述:
第一行输入两个整数 n 和 root,n 表示二叉树的总节点个数,root 表示二叉树的根节点。
以下 n 行每行四个整数 fa,lch,rch,val,表示 fa 的左儿子为 lch,右儿子为 rch。val 表示 fa 节点的值(如果 lch 为 0 则表示 fa 没有左儿子,rch同理)

输出描述:
输出一个整数表示最长链的长度。

示例1

输入
9 1
1 2 3 -3
2 4 5 3
4 0 0 1
5 8 9 0
8 0 0 1
9 0 0 6
3 6 7 -9
6 0 0 2
7 0 0 1
6

输出
4

第一次做; 哈希表前缀和方法; 该方法的通用特点:需要用到前缀和哈希表, preSum, (每个元素的位置信息); 在二叉树中使用该方法要单独注意: 如果curSum是在当前层产生的, 那么需要将curSum从sumMap中删掉, 避免出现一个分支使用了另一个分支上的前缀和的错误情况; 递归函数逻辑: 求以当前节点为结尾的所有路径上和为k的最长路径; 比左神方法中的递归函数少用了一个参数:maxLen, 这个值仅作为返回值即可, 不用作为形参

import java.util.Scanner;
import java.util.HashMap;

public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] str = sc.nextLine().split(" ");
int n = Integer.parseInt(str[0]);
int r = Integer.parseInt(str[1]);
TreeNode[] nodes = new TreeNode[n+1];
for(int i=1; i<=n; i++){
nodes[i] = new TreeNode(0);
}
for(int i=0; i<n; i++){
str = sc.nextLine().split(" ");
int index = Integer.parseInt(str[0]);
int leftIndex = Integer.parseInt(str[1]);
int rightIndex = Integer.parseInt(str[2]);
int val = Integer.parseInt(str[3]);
nodes[index].val = val;
nodes[index].left = nodes[leftIndex];
nodes[index].right = nodes[rightIndex];
}
int k = Integer.parseInt(sc.nextLine());
//
TreeNode root = nodes[r];
//key是前缀和, value是前缀和最早出现的层数
HashMap<Integer, Integer> sumMap = new HashMap<>();
//极其重要的初始化, 这个初始化可以找出以根节点开始的路径
sumMap.put(0,-1);
//根节点在第0层
int res = core(root, sumMap, 0, 0, k);
System.out.println(res);
}
//max既作为返回值,又作为函数参数? 这样就不用把max设成全局变量了
public static int core(TreeNode root, HashMap<Integer, Integer> sumMap, int preSum, int level, int k){
//base case
if(root==null)
return 0;
//
int max = 0;
int curSum = preSum + root.val;
if(!sumMap.containsKey(curSum))
sumMap.put(curSum, level);
if(sumMap.containsKey(curSum-k)){
//以root结尾的路径和为k的最长路径
max = Math.max(max, level - sumMap.get(curSum-k));
}
//新条件新递归; 以左子树各个节点为结尾的结果; 以右子树各个节点为结尾的结果
int leftRes = core(root.left, sumMap, curSum, level+1, k);
int rightRes = core(root.right, sumMap, curSum, level+1, k);
/*
核心: 恢复现场;
如果curSum是在当前层加入sumMap的,curSum删掉(也就是把以当前节点结尾的前缀和删掉);
不删掉的话出现某一个分支使用了另一个分支上的前缀和的情况, 这样就错了;
这是哈希表前缀和方法应用在二叉树上时要特别注意的
*/
if(sumMap.get(curSum)==level)
sumMap.remove(curSum);
//最终返回三者中最大的
return Math.max(max, Math.max(leftRes, rightRes));
}
public static class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int val){
this.val = val;
}
}
}


举报

相关推荐

0 条评论