美文网首页
左神算法笔记——二叉树最长路径累加和

左神算法笔记——二叉树最长路径累加和

作者: yaco | 来源:发表于2020-04-07 10:20 被阅读0次

题目

给定一棵二叉树的头节点head,和一个整数sum,二叉树每个节点上都有数字,我们规定路径必须是从上往下的,求二叉树上累加和为sum的最长路径长度。

分析

  • 这题首先必须考虑到累加和为sum的路径有两种情况,可能是从根节点开始累加的,也有可能是从某一个子节点开始累加的。
  • 所以这题的递归思路一定要考虑清楚边界条件和返回值。
  • 因为不一定从根节点开始累加,所以我们必须从根节点一直遍历到子节点为null,而要求的参数maxLen(最大长度)可以作为回溯体中一个不断更新的变量,用作最终输出。
  • 将从根节点开始的每一层的累加和都存储在一个Hashmap中,如果从根节点一直向下走到某个节点的累加和为curSum, 且curSum - sum在我们之前存储的每一层的累加和中出现过,那么此处就可以更新maxLen
  • 最后一个非常关键的步骤,二叉树从上到下走到空节点的一条路径走完,返回上一层节点而选择走另一条路径时,必须前一个路径的根节点的键值对从map中移除。

代码

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    /**
     * 求和为sum的最大路径长度
     * @param head
     * @param sum
     * @return
     */
    public static int getMaxLength(Node head, int sum) {
        HashMap<Integer, Integer> sumMap = new HashMap<Integer, Integer>();
        sumMap.put(0, 0); // important, 0层累加和为0
        return preOrder(head, sum, 0, 1, 0, sumMap);
    }

    public static int preOrder(Node head, int sum, int preSum, int level,
                               int maxLen, HashMap<Integer, Integer> sumMap) {
        if (head == null) {
            return maxLen;
        }
        int curSum = preSum + head.value;
        if (!sumMap.containsKey(curSum)) {
            sumMap.put(curSum, level);
        }
        if (sumMap.containsKey(curSum - sum)) {   // 更新最大的长度
            // 更新最大的长度
            // 初始化扔了一个0,0在里面,所以如果有从根节点开始的累加和为sum,那么curSum-sum = 0,肯定在map里面,更新当前的level-0;
            // 如果当前的累加和超过了sum,那么其实递归不会在这里结束,会继续向下执行,一直走到节点为null时,返回当前的maxLen
            // 所以当累加和超过sum时,就会检查map中是否存在curSum - sum 的键值对,他的含义就是这条链起始位置不是根节点
            maxLen = Math.max(level - sumMap.get(curSum - sum), maxLen);
        }
        maxLen = preOrder(head.left, sum, curSum, level + 1, maxLen, sumMap);  // 向左进入递归,求maxLen
        maxLen = preOrder(head.right, sum, curSum, level + 1, maxLen, sumMap); // 再向右进入递归,这里会将左递归出来maxLen扔进去,不做计算,只用作比较
        // 这一步的目的就是保证当前map中的存放的键值对,都可以走到当前点的位置
        if (level == sumMap.get(curSum)) {
            sumMap.remove(curSum);
        }
        // 返回结果
        return maxLen;
    }

    // for test -- print tree(左神提供的二叉树直观呈现)
    public static void printTree(Node head) {
        System.out.println("Binary Tree:");
        printInOrder(head, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(Node head, int height, String to, int len) {
        if (head == null) {
            return;
        }
        printInOrder(head.right, height + 1, "v", len);
        String val = to + head.value + to;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(head.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }

    // 测试函数
    public static void main(String[] args) {
        Node head = new Node(-3);
        head.left = new Node(3);
        head.right = new Node(-9);
        head.left.left = new Node(1);
        head.left.right = new Node(0);
        head.left.right.left = new Node(1);
        head.left.right.right = new Node(6);
        head.right.left = new Node(2);
        head.right.right = new Node(1);
        printTree(head);
        System.out.println(getMaxLength(head, 4));
        System.out.println(getMaxLength(head, 9));
    }

补充

对从SumMap中移除curSum的理解

        // 这一步的目的就是保证当前map中的存放的键值对,都可以走到当前点的位置
        if (level == sumMap.get(curSum)) {
            sumMap.remove(curSum);
        }
  • 举实例说明,分析递归遍历过程


相关文章

  • 左神算法笔记——二叉树最长路径累加和

    题目 给定一棵二叉树的头节点head,和一个整数sum,二叉树每个节点上都有数字,我们规定路径必须是从上往下的,求...

  • 二叉树题目

    1. 路径之和 题目 给定一个二叉树root和整数sum,找出所有从根节点到叶节点的路径,这些路径上的节点值累加和...

  • 每日Leetcode—算法(11)

    110.平衡二叉树 算法: 111.二叉树的最小树深 算法: 112.路径总和 算法:

  • 最长路径算法

    一、定义 最长路径算法类似于基于拓扑排序的最短路径算法。本文只针对加权有向无环图讨论。 二、基本思想 对于一幅加权...

  • 二叉树遍历

    看了左程云老师的算法课,记录学习过程,整理思路和形成系统认识。 题目(算法课第五课) 二叉树遍历。二叉树定义,和二...

  • 2018字节跳动 后端开发实习(深圳)一面记录

    面试完整个人都不好了,虽然很菜,当想记录下来,激励自己成长。 二叉树找最长路径给定一颗二叉树,求其中的最长路径。所...

  • 06-21:todo

    0、最长连续子序列 最长递增子序列: 核心思路:保持递增,代码如下: 1、二叉树路径和 2、大数加法/大数乘法 3...

  • 543. 二叉树的直径

    一 题目: 二 思路: 分析下,二叉树的最长路径某个结点的左孩子最大深度加右孩子的最大深度 我们只需要找出每一个节...

  • 翻转二叉树(Java)

    翻转二叉树 对于此题而言,我们使用深度优先算法来遍历二叉树。 1、深度优先算法是根据二叉树的路径进行遍历2、广度优...

  • 二叉树的层平均值(Java)——算法刷题打卡

    二叉树的层平均值 对于此题而言,我们使用广度优先算法来遍历二叉树。 1、深度优先算法是根据二叉树的路径进行遍历2、...

网友评论

      本文标题:左神算法笔记——二叉树最长路径累加和

      本文链接:https://www.haomeiwen.com/subject/kezwphtx.html