Skip to content

Commit

Permalink
Merge branch 'DaleStudy:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
jdy8739 authored Feb 22, 2025
2 parents 68f3621 + 3887c3b commit 9fbd3df
Show file tree
Hide file tree
Showing 20 changed files with 892 additions and 0 deletions.
39 changes: 39 additions & 0 deletions binary-tree-maximum-path-sum/Chaedie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right

"""
Solution: DFS
1) dfs ๋กœ left, right ๊ฐ๊ฐ์˜ max ๊ฐ’์„ ๊ตฌํ•œ๋‹ค.
2) maxSum ์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ ,
3) return value ๋กœ๋Š” leftMax ๋˜๋Š” rightMax ์™€์˜ ํ•ฉ๋งŒ ๋ฆฌํ„ดํ•œ๋‹ค.
(left, right ๋ฅผ ๋‘˜ ๋‹ค ํฌํ•จํ•˜๋Š” ๊ฒฝ์šฐ์™€ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋งŒ ์„ ํƒํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋‚˜๋ˆ”)
Time: O(n)
Space: O(n)
"""


class Solution:
def maxPathSum(self, root: Optional[TreeNode]) -> int:
maxSum = root.val

def dfs(root):
nonlocal maxSum
if not root:
return 0

leftMax = dfs(root.left)
rightMax = dfs(root.right)
leftMax = max(leftMax, 0)
rightMax = max(rightMax, 0)

maxSum = max(maxSum, root.val + leftMax + rightMax)
return root.val + max(leftMax, rightMax)

dfs(root)
return maxSum
47 changes: 47 additions & 0 deletions binary-tree-maximum-path-sum/gwbaik9717.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Time complexity: O(n)
// Space complexity: O(n)

/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
var maxPathSum = function (root) {
let answer = Number.MIN_SAFE_INTEGER;

const dfs = (current) => {
const candidates = [current.val];

if (current.left) {
dfs(current.left);
candidates.push(current.left.val + current.val);
}

if (current.right) {
dfs(current.right);
candidates.push(current.right.val + current.val);
}

// ํ˜„์žฌ ๋…ธ๋“œ๊ฐ€ ๋ฃจํŠธ์ผ ๊ฒฝ์šฐ
if (current.left && current.right) {
answer = Math.max(
answer,
current.left.val + current.right.val + current.val
);
}

current.val = Math.max(...candidates);
answer = Math.max(answer, current.val);
};

dfs(root);

return answer;
};
39 changes: 39 additions & 0 deletions graph-valid-tree/Chaedie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
Conditions of Valid Tree
1) no Loop
2) all nodes has to be connected
Time: O(node + edge)
Space: O(node + edge)
"""


class Solution:
def validTree(self, n: int, edges: List[List[int]]) -> bool:
if not n:
return True
if len(edges) != n - 1:
return False

# Make Graph
graph = {i: [] for i in range(n)}
for n1, n2 in edges:
graph[n1].append(n2)
graph[n2].append(n1)

# loop check
visit = set()

def dfs(i, prev):
if i in visit:
return False

visit.add(i)
for j in graph[i]:
if j == prev:
continue
if not dfs(j, i):
return False
return True

return dfs(0, None) and n == len(visit)
46 changes: 46 additions & 0 deletions graph-valid-tree/KwonNayeon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
Valid Tree์˜ ์กฐ๊ฑด:
1. ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์–ด์•ผ ํ•จ
2. ์‚ฌ์ดํด์ด ์—†์–ด์•ผ ํ•จ
3. edge์˜ ๊ฐœ์ˆ˜๋Š” n-1๊ฐœ
Time Complexity: O(V + E)
- V: ๋…ธ๋“œ์˜ ๊ฐœ์ˆ˜
- E: edge์˜ ๊ฐœ์ˆ˜
Space Complexity: O(V)
- ๋…ธ๋“œ ๋ฐฉ๋ฌธ ์—ฌ๋ถ€๋ฅผ ์ €์žฅํ•˜๋Š” visited set ์‚ฌ์šฉ
ํ’€์ด๋ฐฉ๋ฒ•:
1. ๊ธฐ๋ณธ ์กฐ๊ฑด ์ฒดํฌ: edge์˜ ๊ฐœ์ˆ˜๋Š” n-1๊ฐœ
2. ๊ฐ ๋…ธ๋“œ๋ณ„๋กœ ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ๋“ค์˜ ์ •๋ณด๋ฅผ ์ €์žฅ
- ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์ด๋ฏ€๋กœ ์–‘์ชฝ ๋ชจ๋‘ ์ €์žฅ
3. DFS๋กœ ๋…ธ๋“œ ํƒ์ƒ‰
- 0๋ฒˆ ๋…ธ๋“œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ์—ฐ๊ฒฐ๋œ ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธ
- ์ด๋ฏธ ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ๋Š” ์žฌ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์Œ
4. ๋ชจ๋“  ๋…ธ๋“œ ๋ฐฉ๋ฌธ ํ™•์ธ
- visited์˜ ํฌ๊ธฐ๊ฐ€ n๊ณผ ๊ฐ™๋‹ค๋ฉด ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ ์—ฐ๊ฒฐ๋œ ๊ฒƒ -> valid tree
"""
def validTree(n, edges):
if len(edges) != n - 1:
return False

adj = [[] for _ in range(n)]
for a, b in edges:
adj[a].append(b)
adj[b].append(a)

visited = set()

def dfs(node):
if node in visited:
return

visited.add(node)

for next_node in adj[node]:
dfs(next_node)

dfs(0)
return len(visited) == n

67 changes: 67 additions & 0 deletions graph-valid-tree/dusunax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'''
# 261. Graph Valid Tree
## What constitutes a ๐ŸŒฒ
1. it's a graph.
2. Connected: edges == n - 1, visited node count == n
3. Acyclic: there is no cycle.
## Approach A. DFS
use DFS to check if there is a cycle in the graph.
- if there were no cycle & visited node count == n, return True.
## Approach B. Disjoint Set Union (์„œ๋กœ์†Œ ์ง‘ํ•ฉ)
use Disjoint Set Union to check if there is a cycle in the graph.
- if you find a cycle, return False immediately.
- if you find no cycle, return True.
### Union Find Operation
- Find: find the root of a node.
- if the root of two nodes is already the same, there is a cycle.
- Union: connect two nodes.
## Approach Comparison
- **A. DFS**: simple and easy to understand.
- **B. Disjoint Set Union**: quicker to check if there is a cycle. if there were more edges, Union Find would be faster.
'''
class Solution:
def validTreeDFS(self, n: int, edges: List[List[int]]) -> bool:
if len(edges) != n - 1:
return False

graph = [[] for _ in range(n)]
for node, neighbor in edges:
graph[node].append(neighbor)
graph[neighbor].append(node)

visited = set()
def dfs(node):
visited.add(node)
for neighbor in graph[node]:
if neighbor not in visited:
dfs(neighbor)

dfs(0)
return len(visited) == n

def validTreeUnionFind(self, n: int, edges: List[List[int]]) -> bool:
if len(edges) != n - 1:
return False

parent = [i for i in range(n)]

def find(x):
if x == parent[x]:
return x
parent[x] = find(parent[x])
return parent[x]

def union(x, y):
parent[find(x)] = find(y)

for node, neighbor in edges:
if find(node) == find(neighbor):
return False
union(node, neighbor)

return True
45 changes: 45 additions & 0 deletions graph-valid-tree/mike2ox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Source: https://www.lintcode.com/problem/178/
* Solution: ์œ ํšจํ•œ ํŠธ๋ฆฌ์ธ์ง€ ์ˆœํšŒํ•˜๋ฉด์„œ ํ™•์ธํ•˜๋ฉด ๋˜๊ธฐ์— BFS๋กœ ๊ตฌํ˜„
* ์‹œ๊ฐ„ ๋ณต์žก๋„: O(V + E) - ๋…ธ๋“œ์™€ ๊ฐ„์„ ์— ํ•œ๋ฒˆ์€ ๋ฐฉ๋ฌธ
* ๊ณต๊ฐ„ ๋ณต์žก๋„: O(V + E) - ์ธ์ ‘๋ฆฌ์ŠคํŠธ ๋งŒํผ์˜ ๊ณต๊ฐ„ ํ•„์š”
*/
function validTree(n: number, edges: number[][]): boolean {
// ๊ฐ„์„  ๊ฐœ์ˆ˜ ์ฒดํฌ: ํŠธ๋ฆฌ๋Š” ๋…ธ๋“œ ๊ฐœ์ˆ˜ - 1๊ฐœ์˜ ๊ฐ„์„ ์„ ๊ฐ€์ ธ์•ผ ํ•จ
if (edges.length !== n - 1) return false;

// ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ
const adjList: Map<number, number[]> = new Map();
for (let i = 0; i < n; i++) {
adjList.set(i, []);
}

// ์–‘๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„ ๊ตฌ์„ฑ
for (const [u, v] of edges) {
adjList.get(u)!.push(v);
adjList.get(v)!.push(u);
}

const queue: [number, number][] = [[0, -1]]; // [๋…ธ๋“œ, ๋ถ€๋ชจ๋…ธ๋“œ]
const visited: Set<number> = new Set([0]);

while (queue.length > 0) {
const [node, parent] = queue.shift()!;

// ๋ชจ๋“  ์ด์›ƒ ๋…ธ๋“œ ํ™•์ธ
for (const neighbor of adjList.get(node)!) {
// ๋ถ€๋ชจ ๋…ธ๋“œ๋Š” continue
if (neighbor === parent) continue;

// ์ด๋ฏธ ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ๋ฅผ ๋งŒ๋‚˜๋ฉด ์‚ฌ์ดํด ์กด์žฌ
if (visited.has(neighbor)) return false;

// ์ด์›ƒ ๋…ธ๋“œ๋ฅผ ํ์— ์ถ”๊ฐ€ํ•˜๊ณ  ๋ฐฉ๋ฌธ ํ‘œ์‹œ
visited.add(neighbor);
queue.push([neighbor, node]);
}
}

// ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
return visited.size === n;
}
23 changes: 23 additions & 0 deletions maximum-depth-of-binary-tree/Chaedie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
Solution: BFS
Time: O(n)
Space: O(n)
"""


class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0

q = deque([root])
maxLevel = 0
while q:
maxLevel += 1
for i in range(len(q)):
node = q.popleft()
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return maxLevel
56 changes: 56 additions & 0 deletions maximum-depth-of-binary-tree/KwonNayeon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
Constraints:
- The number of nodes in the tree is in the range [0, 10^4].
- -100 <= Node.val <= 100
Time Complexity: O(N)
- N์€ ํŠธ๋ฆฌ์˜ ๋…ธ๋“œ ์ˆ˜
- ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํ•œ ๋ฒˆ์”ฉ ๋ฐฉ๋ฌธํ•˜๊ธฐ ๋•Œ๋ฌธ
Space Complexity: O(H)
- H๋Š” ํŠธ๋ฆฌ์˜ ๋†’์ด
- ์žฌ๊ท€ ํ˜ธ์ถœ๋กœ ์ธํ•œ ํ˜ธ์ถœ ์Šคํƒ์˜ ์ตœ๋Œ€ ๊นŠ์ด๊ฐ€ ํŠธ๋ฆฌ์˜ ๋†’์ด์™€ ๊ฐ™์Œ
ํ’€์ด๋ฐฉ๋ฒ•:
1. Base case: root๊ฐ€ None์ธ ๊ฒฝ์šฐ 0์„ ๋ฐ˜ํ™˜
2. ์žฌ๊ท€๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์™ผ์ชฝ๊ณผ ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ ๊นŠ์ด๋ฅผ ๊ฐ๊ฐ ๊ณ„์‚ฐ
3. ๋‘ ์„œ๋ธŒํŠธ๋ฆฌ์˜ ๊นŠ์ด ์ค‘ ์ตœ๋Œ€๊ฐ’์— 1์„ ๋”ํ•ด์„œ ๋ฐ˜ํ™˜ (ํ˜„์žฌ ๋…ธ๋“œ์˜ ๊นŠ์ด๋ฅผ ํฌํ•จ)
"""
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right

# Solution 1: ์žฌ๊ท€
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0

left_depth = self.maxDepth(root.left)
right_depth = self.maxDepth(root.right)

return max(left_depth, right_depth) + 1

# Solution 2: ๋ฐ˜๋ณต๋ฌธ
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0

stack = [(root, 1)]
max_depth = 0

while stack:
current, depth = stack.pop()

max_depth = max(max_depth, depth)

if current.left:
stack.append((current.left, depth + 1))
if current.right:
stack.append((current.right, depth + 1))

return max_depth
Loading

0 comments on commit 9fbd3df

Please sign in to comment.