-
Notifications
You must be signed in to change notification settings - Fork 125
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'DaleStudy:main' into main
- Loading branch information
Showing
20 changed files
with
892 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.