Skip to content

Commit fb59771

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents 972490d + d198ece commit fb59771

File tree

128 files changed

+5173
-14
lines changed

Some content is hidden

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

128 files changed

+5173
-14
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* [Problem]: [124 Binary Tree Maximum Path Sum
3+
* (https://leetcode.com/problems/binary-tree-maximum-path-sum/description/)
4+
*/
5+
/**
6+
* Definition for a binary tree node.
7+
* class TreeNode {
8+
* val: number
9+
* left: TreeNode | null
10+
* right: TreeNode | null
11+
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
12+
* this.val = (val===undefined ? 0 : val)
13+
* this.left = (left===undefined ? null : left)
14+
* this.right = (right===undefined ? null : right)
15+
* }
16+
* }
17+
*/
18+
19+
//시간복잡도 O(n)
20+
//공간복잡도 O(h)
21+
function maxPathSum(root: TreeNode | null): number {
22+
if (!root) return 0;
23+
let result = root.val;
24+
25+
function dfs(node: TreeNode | null) {
26+
if (!node) return 0;
27+
28+
let leftMax = Math.max(dfs(node.left), 0);
29+
let rightMax = Math.max(dfs(node.right), 0);
30+
31+
result = Math.max(node.val + leftMax + rightMax, result);
32+
33+
return node.val + Math.max(leftMax, rightMax);
34+
}
35+
36+
dfs(root);
37+
return result;
38+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* <a href="https://leetcode.com/problems/binary-tree-maximum-path-sum/">week11-5. binary-tree-maximum-path-sum</a>
3+
* <li>Description: Given the root of a binary tree, return the maximum path sum of any non-empty path</li>
4+
* <li>Topics: Dynamic Programming, Tree, Depth-First Search, Binary Tree</li>
5+
* <li>Time Complexity: O(N), Runtime 0ms </li>
6+
* <li>Space Complexity: O(H), Memory 44.1MB</li>
7+
*/
8+
class Solution {
9+
public int maxPathSum(TreeNode root) {
10+
dfs(root);
11+
return max;
12+
}
13+
14+
int max = Integer.MIN_VALUE;
15+
public int dfs(TreeNode head) {
16+
if (head == null) return 0;
17+
18+
int left = Math.max(0, dfs(head.left));
19+
int right = Math.max(0, dfs(head.right));
20+
21+
max = Math.max(max, head.val + left + right);
22+
23+
return head.val + Math.max(left, right);
24+
}
25+
26+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* 문제 설명
3+
* - 주어진 이진 트리에서 최대 경로 합을 구하는 문제
4+
*
5+
* 아이디어
6+
* 1) 분할정복 + DFS
7+
* - DFS 아이디어: 각 노드를 루트로 하는 서브트리에서, 해당 노드를 포함한 최대 경로 합을 구해 전역 변수 maxSum을 업데이트한다.
8+
* - 현재 노드 기준의 최대 경로 합은: 현재 노드의 값 + 왼쪽 서브트리에서의 최대 경로 + 오른쪽 서브트리에서의 최대 경로.
9+
* - 하지만 dfs 함수의 반환값은 부모 노드에 연결될 수 있는 일방향 경로이므로,
10+
* '현재 노드의 값 + (왼쪽 또는 오른쪽 중 더 큰 값)'을 반환해야 한다.
11+
*/
12+
13+
/**
14+
* Definition for a binary tree node.
15+
* class TreeNode {
16+
* val: number
17+
* left: TreeNode | null
18+
* right: TreeNode | null
19+
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
20+
* this.val = (val===undefined ? 0 : val)
21+
* this.left = (left===undefined ? null : left)
22+
* this.right = (right===undefined ? null : right)
23+
* }
24+
* }
25+
*/
26+
27+
class TreeNode {
28+
val: number;
29+
left: TreeNode | null;
30+
right: TreeNode | null;
31+
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
32+
this.val = val === undefined ? 0 : val;
33+
this.left = left === undefined ? null : left;
34+
this.right = right === undefined ? null : right;
35+
}
36+
}
37+
38+
function maxPathSum(root: TreeNode | null): number {
39+
let maxSum = -Infinity;
40+
41+
function dfs(node: TreeNode | null) {
42+
if (!node) return 0;
43+
44+
const leftMaxSum = Math.max(dfs(node.left), 0);
45+
const rightMaxSum = Math.max(dfs(node.right), 0);
46+
const current = leftMaxSum + rightMaxSum + node.val;
47+
maxSum = Math.max(current, maxSum);
48+
49+
return node.val + Math.max(leftMaxSum, rightMaxSum);
50+
}
51+
52+
dfs(root);
53+
54+
return maxSum;
55+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
public class Solution {
2+
private int maxSum;
3+
4+
public int maxPathSum(TreeNode root) {
5+
maxSum = root.val;
6+
dfs(root);
7+
return maxSum;
8+
}
9+
10+
private int dfs(TreeNode node) {
11+
if (node == null) {
12+
return 0;
13+
}
14+
15+
int leftMax = Math.max(dfs(node.left), 0);
16+
int rightMax = Math.max(dfs(node.right), 0);
17+
18+
maxSum = Math.max(maxSum, node.val + leftMax + rightMax);
19+
20+
return node.val + Math.max(leftMax, rightMax);
21+
}
22+
}
23+

course-schedule/minji-go.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* <a href="https://leetcode.com/problems/course-schedule/">week10-3. course-schedule </a>
3+
* <li>Description: Return true if you can finish all courses. Otherwise, return false </li>
4+
* <li>Topics: Depth-First Search, Breadth-First Search, Graph, Topological Sort </li>
5+
* <li>Time Complexity: O(N+E), Runtime 7ms </li>
6+
* <li>Space Complexity: O(N+E), Memory 45.68MB </li>
7+
* <li>Note : refer to the answer. remember the topic of topological sort </li>
8+
*/
9+
class Solution {
10+
public boolean canFinish(int numCourses, int[][] prerequisites) {
11+
int[] inDegree = new int[numCourses];
12+
List<List<Integer>> graph = new ArrayList<>();
13+
for (int i=0; i<numCourses; i++){
14+
graph.add(new ArrayList<>());
15+
}
16+
17+
for(int[] pre : prerequisites) {
18+
int dest = pre[0], src = pre[1];
19+
graph.get(src).add(dest);
20+
inDegree[dest]++;
21+
}
22+
23+
Queue<Integer> queue = new LinkedList<>();
24+
for (int i=0; i<numCourses; i++) {
25+
if(inDegree[i] == 0) {
26+
queue.offer(i);
27+
}
28+
}
29+
30+
int count = 0;
31+
while(!queue.isEmpty()){
32+
int node = queue.poll();
33+
count++;
34+
35+
for(int neighbor : graph.get(node)) {
36+
inDegree[neighbor]--;
37+
if(inDegree[neighbor] == 0) {
38+
queue.offer(neighbor);
39+
}
40+
}
41+
}
42+
43+
return count == numCourses;
44+
}
45+
}

graph-valid-tree/HoonDongKang.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* [Problem]: [178] Graph Valid Tree
3+
* (https://www.lintcode.com/problem/178/)
4+
*/
5+
6+
export class Solution {
7+
/**
8+
* @param n: An integer
9+
* @param edges: a list of undirected edges
10+
* @return: true if it's a valid tree, or false
11+
*/
12+
//시간복잡도 O(n+e)
13+
//공간복잡도 O(n+e)
14+
validTree(n: number, edges: number[][]): boolean {
15+
const graph: number[][] = Array.from({ length: n }, () => []);
16+
for (const [a, b] of edges) {
17+
graph[a].push(b);
18+
graph[b].push(a);
19+
}
20+
21+
const visited = new Set<number>();
22+
23+
function hasCycle(node: number, prev: number): boolean {
24+
if (visited.has(node)) return true;
25+
visited.add(node);
26+
27+
for (const neighbor of graph[node]) {
28+
if (neighbor === prev) continue;
29+
if (hasCycle(neighbor, node)) return true;
30+
}
31+
return false;
32+
}
33+
34+
if (hasCycle(0, -1)) return false;
35+
36+
return visited.size === n;
37+
}
38+
39+
//시간복잡도 O(n)
40+
//공간복잡도 O(n)
41+
validTree2(n: number, edges: number[][]): boolean {
42+
if (edges.length !== n - 1) return false;
43+
44+
const graph: number[][] = Array.from({ length: n }, () => []);
45+
for (const [a, b] of edges) {
46+
graph[a].push(b);
47+
graph[b].push(a);
48+
}
49+
50+
const visited = new Set<number>();
51+
52+
function dfs(node: number) {
53+
visited.add(node);
54+
for (const neighbor of graph[node]) {
55+
if (!visited.has(neighbor)) {
56+
dfs(neighbor);
57+
}
58+
}
59+
}
60+
61+
dfs(0);
62+
63+
return visited.size === n;
64+
}
65+
}

graph-valid-tree/hi-rachel.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""
2+
- 정점 개수 n, 간선 배열 edges
3+
- 무방향 그래프
4+
5+
트리 조건
6+
1. 완전히 연결된 그래프여야 함 -> 전체 탐색 가능
7+
2. 그래프에 순환하는 부분이 없어야 함
8+
9+
트리 특성상 항상 e = n - 1, 즉 간선의 수 = 노드의 개수 - 1
10+
11+
TC: O(n)
12+
SC: O(n)
13+
"""
14+
15+
from typing import List
16+
17+
class Solution:
18+
def validTree(self, n: int, edges: List[List[int]]) -> bool:
19+
graph = [[] for _ in range(n)]
20+
visited = set()
21+
22+
for a, b in edges:
23+
graph[a].append(b)
24+
graph[b].append(a)
25+
26+
def has_cycle(node, prev):
27+
# 이미 방문 = 순환 -> 트리 x
28+
if node in visited:
29+
return True
30+
visited.add(node)
31+
for adj in graph[node]:
32+
if adj == prev:
33+
continue
34+
if has_cycle(adj, node):
35+
return True
36+
37+
return False
38+
39+
if has_cycle(0, -1):
40+
return False
41+
42+
return len(visited) == n

graph-valid-tree/soobing.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* 문제 설명
3+
* - 주어진 간선 정보로 트리가 만들어지는지 확인하는 문제
4+
* - 어려웠음 다시 풀어보기 ⚠️
5+
*
6+
* 트리의 조건
7+
* 1) 모든 노드가 연결되어 있어야 한다.
8+
* 2) 사이클이 없어야 한다.
9+
* 3) 총 간선의 갯수는 n-1개여야 한다.
10+
*
11+
* 아이디어
12+
* 1) Union-Find (Disjoint Set)
13+
* 2) DFS ✅
14+
*/
15+
function validTree(n, edges) {
16+
if (edges.length !== n - 1) return false; // 간선 수가 n - 1이 아니면 트리 불가
17+
18+
const graph = Array.from({ length: n }, () => []);
19+
for (const [a, b] of edges) {
20+
graph[a].push(b);
21+
graph[b].push(a);
22+
}
23+
24+
const visited = new Set();
25+
26+
const dfs = (node, prev) => {
27+
if (visited.has(node)) return false;
28+
visited.add(node);
29+
30+
for (const neighbor of graph[node]) {
31+
if (neighbor === prev) continue; // 바로 이전 노드는 무시, 체크하는 이유: 무방향 그래프이기 때문에 사이클로 들어가게 하지 않기 위함.
32+
if (!dfs(neighbor, node)) return false; // 사이클 발생
33+
}
34+
35+
return true;
36+
};
37+
38+
if (!dfs(0, -1)) return false;
39+
40+
return visited.size === n;
41+
}

graph-valid-tree/sora0319.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
public class Solution {
2+
public boolean validTree(int n, int[][] edges) {
3+
Map<Integer, List<Integer>> graph = new HashMap<>();
4+
for (int i = 0; i < n; i++) {
5+
graph.put(i, new ArrayList<>());
6+
}
7+
8+
for (int[] edge : edges) {
9+
int node = edge[0];
10+
int adj = edge[1];
11+
graph.get(node).add(adj);
12+
graph.get(adj).add(node);
13+
}
14+
15+
Set<Integer> visited = new HashSet<>();
16+
if (inCycle(0, -1, graph, visited)) {
17+
return false;
18+
}
19+
20+
return visited.size() == n;
21+
}
22+
23+
private boolean inCycle(int node, int prev, Map<Integer, List<Integer>> graph, Set<Integer> visited) {
24+
if (visited.contains(node)) {
25+
return true;
26+
}
27+
28+
visited.add(node);
29+
30+
for (int neighbor : graph.get(node)) {
31+
if (neighbor == prev) continue;
32+
if (inCycle(neighbor, node, graph, visited)) {
33+
return true;
34+
}
35+
}
36+
37+
return false;
38+
}
39+
}
40+

0 commit comments

Comments
 (0)