Skip to content

Commit dd1981a

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents face40a + 098c1b0 commit dd1981a

File tree

88 files changed

+2856
-45
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+2856
-45
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class TreeNode {
2+
val: number;
3+
left: TreeNode | null;
4+
right: TreeNode | null;
5+
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
6+
this.val = val === undefined ? 0 : val;
7+
this.left = left === undefined ? null : left;
8+
this.right = right === undefined ? null : right;
9+
}
10+
}
11+
12+
// TC: O(n)
13+
// SC: O(n)
14+
function maxPathSum(root: TreeNode | null): number {
15+
let maxSum = -Infinity;
16+
17+
const dfs = (node: TreeNode | null) => {
18+
if (!node) return 0;
19+
20+
const leftMax = Math.max(dfs(node.left), 0);
21+
const rightMax = Math.max(dfs(node.right), 0);
22+
23+
maxSum = Math.max(node.val + leftMax + rightMax, maxSum);
24+
25+
return node.val + Math.max(leftMax, rightMax);
26+
};
27+
28+
dfs(root);
29+
return maxSum;
30+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class Solution {
2+
public:
3+
int dfs(TreeNode* root, int& result){
4+
if(root == nullptr)
5+
return 0;
6+
7+
int left = max(0, dfs(root->left, result));
8+
int right = max(0, dfs(root->right, result));
9+
int sum = root->val + left + right;
10+
11+
result = max(result, sum);
12+
13+
return root->val + max(left, right);
14+
}
15+
16+
int maxPathSum(TreeNode* root) {
17+
int result = INT_MIN;
18+
19+
dfs(root, result);
20+
return result;
21+
}
22+
};
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* public class TreeNode {
4+
* int val;
5+
* TreeNode left;
6+
* TreeNode right;
7+
* TreeNode() {}
8+
* TreeNode(int val) { this.val = val; }
9+
* TreeNode(int val, TreeNode left, TreeNode right) {
10+
* this.val = val;
11+
* this.left = left;
12+
* this.right = right;
13+
* }
14+
* }
15+
*/
16+
class Solution {
17+
18+
// 최대 Path 누적 합
19+
int maxPathSumVal = Integer.MIN_VALUE;
20+
21+
// 시간복잡도: O(n), 공간복잡도: O(h) h as height of tree
22+
public int maxPathSum(TreeNode root) {
23+
maxPathSumChecker(root);
24+
return maxPathSumVal;
25+
}
26+
27+
// 재귀
28+
private int maxPathSumChecker(TreeNode node) {
29+
30+
if (node == null) {
31+
return 0;
32+
}
33+
34+
int leftMax = Math.max(maxPathSumChecker(node.left), 0);
35+
int rightMax = Math.max(maxPathSumChecker(node.right), 0);
36+
37+
maxPathSumVal = Math.max(node.val + leftMax + rightMax, maxPathSumVal);
38+
39+
return node.val + Math.max(leftMax, rightMax);
40+
}
41+
}
42+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from typing import Optional
2+
3+
class TreeNode:
4+
def __init__(self, val=0, left=None, right=None):
5+
self.val = val
6+
self.left = left
7+
self.right = right
8+
class Solution:
9+
"""
10+
- Time Complexity: O(n), n = The number of nodes
11+
- Space Complexity: O(H), H = The height of Tree
12+
"""
13+
def maxPathSum(self, root: Optional[TreeNode]) -> int:
14+
self.max_sum = float("-inf")
15+
16+
def dfs(node):
17+
if not node:
18+
return 0
19+
20+
# Find max sum from the left and right children (more than 0)
21+
l_sum = max(dfs(node.left), 0)
22+
r_sum = max(dfs(node.right), 0)
23+
24+
# Calculate current sum and update max_sum
25+
current_sum = node.val + l_sum + r_sum
26+
self.max_sum = max(self.max_sum, current_sum)
27+
28+
# Return larger path
29+
return node.val + max(l_sum, r_sum)
30+
31+
dfs(root)
32+
33+
return self.max_sum
34+
35+
def do_test():
36+
sol = Solution()
37+
38+
root1 = TreeNode(1)
39+
root1.left = TreeNode(2)
40+
root1.right = TreeNode(3)
41+
e1 = 6
42+
r1 = sol.maxPathSum(root1)
43+
print(f"TC 1 is Passed!" if r1 == e1 else f"TC 1 is Failed! - Expected: {e1}, Result: {r1}")
44+
45+
root2 = TreeNode(-10)
46+
root2.left = TreeNode(9)
47+
root2.right = TreeNode(20)
48+
root2.right.left = TreeNode(15)
49+
root2.right.right = TreeNode(7)
50+
e2 = 42
51+
r2 = sol.maxPathSum(root2)
52+
print(f"TC 2 is Passed!" if r2 == e2 else f"TC 2 is Failed! - Expected: {e2}, Result: {r2}")
53+
54+
do_test()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* https://leetcode.com/problems/binary-tree-maximum-path-sum/
3+
* Definition for a binary tree node.
4+
* function TreeNode(val, left, right) {
5+
* this.val = (val===undefined ? 0 : val)
6+
* this.left = (left===undefined ? null : left)
7+
* this.right = (right===undefined ? null : right)
8+
* }
9+
*/
10+
/**
11+
* @param {TreeNode} root
12+
* @return {number}
13+
*/
14+
var maxPathSum = function (root) {
15+
let maxSum = -Infinity; // global max
16+
17+
function dfs(node) {
18+
if (!node) return 0;
19+
20+
// 왼쪽과 오른쪽 서브트리에서 최대 경로 합을 구한다
21+
// 음수면 0으로 치환 (해당 서브트리를 포함하지 않는게 더 이득인 경우)
22+
let leftMax = Math.max(0, dfs(node.left));
23+
let rightMax = Math.max(0, dfs(node.right));
24+
25+
// 현재 노드를 루트로 하는 경로에서 최대값을 계산 (left + node + right)
26+
let currentMax = leftMax + node.val + rightMax;
27+
28+
// global 최대값 갱신
29+
maxSum = Math.max(maxSum, currentMax);
30+
31+
// 부모 노드로 return 시: 한쪽 방향으로만 선택 가능
32+
return node.val + Math.max(leftMax, rightMax);
33+
}
34+
35+
dfs(root);
36+
return maxSum;
37+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class Solution {
2+
public:
3+
int maxPathSum(TreeNode* root) {
4+
int res = INT_MIN;
5+
6+
dfs(root, res);
7+
return res;
8+
}
9+
10+
int dfs(TreeNode* root, int& res) {
11+
if (!root)
12+
return 0;
13+
14+
// 좌측 부분트리, 우측 부분트리를 각각 계산할 때 dfs의 '반환값'을 활용
15+
// 음수값이 나올 경우는 0으로 대체함
16+
int left = max(0, dfs(root->left, res));
17+
int right = max(0, dfs(root->right, res));
18+
19+
// 최종 반환할 값 업데이트
20+
// 좌측 트리, 우측 트리, 루트 노드를 모두 통과하는 경로가 현재까지 최댓값인지 비교해서 갱신
21+
res = max(res, root->val + left + right);
22+
23+
// 상위 노드로 전달되는 값은 root의 값을 포함하는 경로의 값이다
24+
// 따라서 좌측 트리 혹은 우측 트리 중 하나의 경로만을 선택해서 통과할 수 있다
25+
return root->val + max(left, right);
26+
}
27+
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* class TreeNode {
4+
* val: number
5+
* left: TreeNode | null
6+
* right: TreeNode | null
7+
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
8+
* this.val = (val===undefined ? 0 : val)
9+
* this.left = (left===undefined ? null : left)
10+
* this.right = (right===undefined ? null : right)
11+
* }
12+
* }
13+
*/
14+
15+
/*
16+
Time complexity: O(N)
17+
Space complexity: O(N) h: 트리의 높이
18+
*/
19+
function maxPathSum(root: TreeNode | null): number {
20+
let maxSum = -Infinity
21+
const dfs = (node: TreeNode): number => {
22+
if (node == null) return 0
23+
24+
const leftMax = Math.max(0, dfs(node.left))
25+
const rightMax = Math.max(0, dfs(node.right))
26+
const currentMax = node.val + leftMax + rightMax
27+
28+
maxSum = Math.max(maxSum, currentMax)
29+
return node.val + Math.max(leftMax, rightMax)
30+
}
31+
dfs(root)
32+
return maxSum
33+
};
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* function TreeNode(val, left, right) {
4+
* this.val = (val===undefined ? 0 : val);
5+
* this.left = (left===undefined ? null : left);
6+
* this.right = (right===undefined ? null : right);
7+
* }
8+
*/
9+
10+
/**
11+
* @param {TreeNode} root
12+
* @return {number}
13+
*/
14+
var maxPathSum = function(root) {
15+
let res = [root.val];
16+
17+
function dfs(node) {
18+
if (!node) return 0;
19+
20+
let leftMax = dfs(node.left);
21+
let rightMax = dfs(node.right);
22+
23+
leftMax = Math.max(leftMax, 0);
24+
rightMax = Math.max(rightMax, 0);
25+
26+
// 경유지점 포함한 경로 최대값 업데이트
27+
res[0] = Math.max(res[0], node.val + leftMax + rightMax);
28+
29+
// 분기하지 않는 경로에서의 최대값 리턴
30+
return node.val + Math.max(leftMax, rightMax);
31+
}
32+
33+
dfs(root);
34+
return res[0];
35+
};
36+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
var maxPathSum = function (root) {
2+
let maxSum = -Infinity;
3+
4+
function dfs(node) {
5+
if (node === null) return 0; // 6) Base Case
6+
const left = Math.max(dfs(node.left), 0); // 8) Pruning
7+
const right = Math.max(dfs(node.right), 0); // 8) Pruning
8+
9+
const currentSum = left + node.val + right; // 9) Pivot Sum
10+
maxSum = Math.max(maxSum, currentSum); // 7) Global Max
11+
12+
return node.val + Math.max(left, right); // 10) Return Value
13+
}
14+
15+
dfs(root); // 4) DFS 시작
16+
console.log(maxSum); // 최종 답 출력
17+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Solution:
2+
def maxPathSum(self, root):
3+
self.max_sum = float('-inf')
4+
def dfs(node):
5+
if not node:
6+
return 0
7+
left = max(dfs(node.left), 0)
8+
right = max(dfs(node.right), 0)
9+
self.max_sum = max(self.max_sum, node.val + left + right)
10+
return node.val + max(left, right)
11+
dfs(root)
12+
return self.max_sum
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# https://leetcode.com/problems/binary-tree-maximum-path-sum/
2+
3+
from typing import Optional
4+
5+
# Definition for a binary tree node.
6+
class TreeNode:
7+
def __init__(self, val=0, left=None, right=None):
8+
self.val = val
9+
self.left = left
10+
self.right = right
11+
12+
class Solution:
13+
def maxPathSum(self, root: Optional[TreeNode]) -> int:
14+
"""
15+
[Complexity]
16+
- TC: O(n) (각 node를 한 번씩 방문)
17+
- SC: O(height) (tree의 높이만큼 call stack)
18+
19+
[Approach]
20+
path에는 같은 node가 두 번 들어갈 수 없으므로, 각 node 마다 해당 node를 지난 path의 max sum은 다음과 같이 구할 수 있다.
21+
= (1) left child를 지나는 path의 max_sum
22+
+ (2) right child를 지나는 path의 max_sum
23+
+ (3) 현재 node의 val
24+
따라서 이는 재귀 문제로 풀 수 있으며, 각 단계마다 global max sum과 비교하며 값을 업데이트 하면 된다.
25+
26+
이때 node의 값은 음수가 될 수 있으므로, (1) & (2)가 음수라면 0으로 처리해야 한다. 즉,
27+
= (1) max(get_max_sum(node.left), 0)
28+
+ (2) max(get_max_sum(node.right), 0)
29+
+ (3) 현재 node의 val
30+
과 같이 구하고, global max sum과 이 값을 비교하면 된다.
31+
32+
또한, 현재 보고 있는 node가 get_max_sum() 함수의 반환값은
33+
= 현재 node의 값 + (1) & (2) 중 큰 값
34+
이어야 한다. 왜냐하면 현재 node를 두 번 이상 방문할 수 없기 때문이다.
35+
"""
36+
37+
res = -1001
38+
39+
def get_max_sum(node):
40+
"""주어진 node가 root인 tree에서, root를 지나는 path의 max sum을 구하는 함수"""
41+
nonlocal res
42+
43+
# base condition
44+
if not node:
45+
return 0
46+
47+
# compute left & right child's max path sum
48+
left_max_sum = max(get_max_sum(node.left), 0)
49+
right_max_sum = max(get_max_sum(node.right), 0)
50+
51+
# compute max path sum at this step
52+
max_sum = left_max_sum + right_max_sum + node.val
53+
54+
# update res
55+
res = max(res, max_sum)
56+
57+
return node.val + max(left_max_sum, right_max_sum)
58+
59+
get_max_sum(root)
60+
61+
return res
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
5+
# Outputs
6+
7+
# Constraints
8+
9+
# Ideas
10+
11+
[회고]
12+
13+
"""
14+
15+

0 commit comments

Comments
 (0)