给定一棵二叉树的头节点head,和一个数K。路径的定义:可以从任何一个点开始,但是只能往下走,往下可以走到任何节点停止。返回路径累加和为K的所有路径中,最长的路径最多有几个节点?

问题描述:

        给定一棵二叉树的头节点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));
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值