LeetCode 124. Binary Tree Maximum Path Sum

博客围绕LeetCode上一道二叉树最大路径和的题目展开。题目要求在非空二叉树中找出最大路径和,路径不能分叉。分析指出该题虽难但理解答案后较易明白,通过从case入手,利用递归遍历和贪心思想求解,还提及解题中的多个注意点。

题目

在这里插入图片描述
大意就是说一棵非空的二叉树,然后让你找出树中的最大路径和。所谓路径就是从树中一个结点沿着父子连接的路径构成的路径。
需要注意的是路径不能出现分叉,比如说图中样例2,如果-10改为30,那最大的路径和是从15到20到30再到9,就不能包括7了,因为题目中说了是从一个起点到一个终点,这一点也是解题的关键。

分析

leetcode给这道题的难度划分在了Hard。我觉得有道理也没道理。因为这道题看上去很难很复杂,但又没那么难理解,就像是简单dp题,如果想不明白怎么做确实很难找出最优解,但是看了答案也能很快理解。下面先分析一下这道题。

这题难就难在上来给人手足无措的感觉,因为一棵二叉树的路径有很多种,即使我们一条一条找,先不说很慢,能不能写出来找的代码都不容易。那怎么做呢?不妨从case入手。
先看第二个case,题目中说到,路径是从一个起点到一个终点,可以通过父节点,先假设树中所有的结点值都是正数,不难想象这种路径就是从左孩子到根再到右孩子,这是一种简单的贪心思想。比如case2中的黑体部分,就是从15到20再到7。类似的可以理解case1的情况。明白了这个,我们就可以把求解的代码框架搭起来:
因为我们拿到的是根节点,所以按照递归遍历的思想,不妨从根节点递归遍历到叶子然后再网上回溯,这样我们就能在回溯的时候依次得到一个结点它的左右孩子结点路径之和。
首先我们递归的找到最左边的孩子和最右边的孩子:

int findmaxsum(TreeNode* root, int& maxsum) {
        if (!root) return 0;
        int leftmax = findmaxsum(root->left, maxsum);
        int rightmax = findmaxsum(root->right, maxsum);
}

相信会写递归遍历二叉树的代码就不难理解上面的代码,其中传递的maxsum是我们需要找到的最大路径和。
按理说最大路径和传递了引用,函数就不需要返回值了,那为什么这里函数还需要返回int呢?注意,这个函数返回值并不是最大路径和,而是从孩子结点走到根的路径之和,不懂没关系,先留个印象,只要看到后面完整的部分就能明白。
写到这里,那按照递归遍历,就执行到了最左边的叶子结点,比如case2中的15,由于它是叶子,左右孩子都没有,所以左右子树路径和leftmax和rightmax都是0,所以以15为根节点的子树最大路径和就是0 + 0 + 15,接着就可以写返回值了。
注意这里就是本题的第一个注意点,我们返回的值按理说应该是左子树的值加上右子树的值加上结点的值,但是注意刚才提过的路径不能分叉,这就导致并不能返回15+0+0,比如case2中如果根是30,那从30的右孩子20返回到30的值就不能是20+15+7了,因为路径只可能从30到20再到15或7,所以正确的return应该是return max(leftmax, rightmax) + root->val,即左右孩子的较大者和这个结点的值,结点值必须要,因为路径要连续。
那如果就这么简单写完了肯定是对不起hard难度的,我们刚才考虑leftmax和rightmax的时候,只是无脑的求和,但如果leftmax值或者rightmax值是负数呢?,比方说case2中不是15和7,而是-15和-7呢?那最大路径肯定就是只有20这个结点了,所以这是第二个注意点,怎么解决左右孩子为负数的问题呢?当然可以写一个判断语句,如果是负数就不加,这里做了一个比较巧妙的处理,对leftmax的值和0进行一个max比较,如果比0小就加上0,相当于不加,这样就完美解决了负数的问题。
接着第三个注意点,最大路径和是不一定过根节点的,比如case2就没有过,所以我们最后return的结果其实不一定的最大的,那为了记录遍历过程中最大的路径和,我们传入一个引用参数maxsum,这也是之前代码中疑惑的地方,每次遍历到一个定点,就比较一下maxsum的值和当前点的路径和,这样遍历完得到的maxsum值就是最大的路径和。
说到这里,终于是把这道题的细节说完了,很多注意的点值得这道题作为一个hard。代码如下:

class Solution {
public:
    int findmaxsum(TreeNode* root, int& maxsum) {
        if (!root) return 0;
        int leftmax = max(findmaxsum(root->left, maxsum), 0);
        int rightmax = max(findmaxsum(root->right, maxsum), 0);
        // 比较的时候左右子树和加上根
        maxsum = max(maxsum, leftmax + rightmax + root->val);
        // 返回到上层的只是左右的较大者和根
        return max(leftmax, rightmax) + root->val;
    }
    int maxPathSum(TreeNode* root) {
        int maxsum = INT_MIN;
        findmaxsum(root, maxsum);
        return maxsum;
    }
};
1. Two Sum 2. Add Two Numbers 3. Longest Substring Without Repeating Characters 4. Median of Two Sorted Arrays 5. Longest Palindromic Substring 6. ZigZag Conversion 7. Reverse Integer 8. String to Integer (atoi) 9. Palindrome Number 10. Regular Expression Matching 11. Container With Most Water 12. Integer to Roman 13. Roman to Integer 14. Longest Common Prefix 15. 3Sum 16. 3Sum Closest 17. Letter Combinations of a Phone Number 18. 4Sum 19. Remove Nth Node From End of List 20. Valid Parentheses 21. Merge Two Sorted Lists 22. Generate Parentheses 23. Swap Nodes in Pairs 24. Reverse Nodes in k-Group 25. Remove Duplicates from Sorted Array 26. Remove Element 27. Implement strStr() 28. Divide Two Integers 29. Substring with Concatenation of All Words 30. Next Permutation 31. Longest Valid Parentheses 32. Search in Rotated Sorted Array 33. Search for a Range 34. Find First and Last Position of Element in Sorted Array 35. Valid Sudoku 36. Sudoku Solver 37. Count and Say 38. Combination Sum 39. Combination Sum II 40. First Missing Positive 41. Trapping Rain Water 42. Jump Game 43. Merge Intervals 44. Insert Interval 45. Unique Paths 46. Minimum Path Sum 47. Climbing Stairs 48. Permutations 49. Permutations II 50. Rotate Image 51. Group Anagrams 52. Pow(x, n) 53. Maximum Subarray 54. Spiral Matrix 55. Jump Game II 56. Merge k Sorted Lists 57. Insertion Sort List 58. Sort List 59. Largest Rectangle in Histogram 60. Valid Number 61. Word Search 62. Minimum Window Substring 63. Unique Binary Search Trees 64. Unique Binary Search Trees II 65. Interleaving String 66. Maximum Product Subarray 67. Binary Tree Inorder Traversal 68. Binary Tree Preorder Traversal 69. Binary Tree Postorder Traversal 70. Flatten Binary Tree to Linked List 71. Construct Binary Tree from Preorder and Inorder Traversal 72. Construct Binary Tree from Inorder and Postorder Traversal 73. Binary Tree Level Order Traversal 74. Binary Tree Zigzag Level Order Traversal 75. Convert Sorted Array to Binary Search Tree 76. Convert Sorted List to Binary Search Tree 77. Recover Binary Search Tree 78. Sum Root to Leaf Numbers 79. Path Sum 80. Path Sum II 81. Binary Tree Maximum Path Sum 82. Populating Next Right Pointers in Each Node 83. Populating Next Right Pointers in Each Node II 84. Reverse Linked List 85. Reverse Linked List II 86. Partition List 87. Rotate List 88. Remove Duplicates from Sorted List 89. Remove Duplicates from Sorted List II 90. Intersection of Two Linked Lists 91. Linked List Cycle 92. Linked List Cycle II 93. Reorder List 94. Binary Tree Upside Down 95. Binary Tree Right Side View 96. Palindrome Linked List 97. Convert Binary Search Tree to Sorted Doubly Linked List 98. Lowest Common Ancestor of a Binary Tree 99. Lowest Common Ancestor of a Binary Search Tree 100. Binary Tree Level Order Traversal II
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值