|
| 1 | +/* |
| 2 | +# Time Complexity: O(n) |
| 3 | +# Space Complexity: O(n) |
| 4 | + - 재귀 호출 내부에서 left, right 변수를 사용하고, 재귀 호출 최대 깊이는 n이므로 |
| 5 | +# Solution |
| 6 | +전체 문제를 각 subtree에 대한 문제로 쪼개어 생각할 수 있습니다. |
| 7 | +임의의 노드 x에 대해, x의 왼쪽 자식을 x_l, x의 오른쪽 자식을 x_r, x의 값을 x.val이라고 정의하겠습니다. |
| 8 | +x를 root로 하는 subtree에서 'x를 path의 한쪽 끝으로 하는 path sum 중 최대값'을 dp[x]라고 정의하겠습니다. |
| 9 | +그러면 dp[x] = max(max(0, dp[x_l]) + x.val, max(0, dp[x_r]) + x.val) 로 구할 수 있습니다. (subtree의 dp 값이 음수인 경우는 버리면 되기 때문에.) |
| 10 | +이제 root로부터 출발해서 DFS로 전체 노드를 순회하며 이 점화식을 적용하면, 전체 tree에 대해 dp값을 구할 수 있습니다. |
| 11 | +단, 문제에서 원하는 답은 root를 반드시 path의 한쪽 끝으로 원하는 것은 아니고, 심지어 root가 path에 포함되지 않아도 되기 때문에, |
| 12 | +어중간한(?) (= root를 path에 포함하지 않는) path도 고려할 필요가 있는데요. |
| 13 | +이를 고려하기 위해, 각 재귀 함수 호출마다 max(0, dp[x_l]) + root.val + max(0, dp[x_r]) 값이 정답이 될 수 있는지 체크하는 과정이 필요합니다. |
| 14 | +*/ |
| 15 | +/** |
| 16 | + * Definition for a binary tree node. |
| 17 | + * public class TreeNode { |
| 18 | + * int val; |
| 19 | + * TreeNode left; |
| 20 | + * TreeNode right; |
| 21 | + * TreeNode() {} |
| 22 | + * TreeNode(int val) { this.val = val; } |
| 23 | + * TreeNode(int val, TreeNode left, TreeNode right) { |
| 24 | + * this.val = val; |
| 25 | + * this.left = left; |
| 26 | + * this.right = right; |
| 27 | + * } |
| 28 | + * } |
| 29 | + */ |
| 30 | +class Solution { |
| 31 | + public int ans = -30_000_001; |
| 32 | + public int maxPathSum(TreeNode root) { |
| 33 | + maxInTree(root); |
| 34 | + |
| 35 | + return ans; |
| 36 | + } |
| 37 | + |
| 38 | + public int maxInTree(TreeNode root) { |
| 39 | + if (root == null) { |
| 40 | + return 0; |
| 41 | + } |
| 42 | + |
| 43 | + int left = Math.max(0, maxInTree(root.left)); |
| 44 | + int right = Math.max(0, maxInTree(root.right)); |
| 45 | + |
| 46 | + ans = Math.max(ans, left + root.val + right); |
| 47 | + |
| 48 | + return root.val + Math.max(left, right); |
| 49 | + } |
| 50 | +} |
0 commit comments