Skip to content

Commit 42ae345

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents 495139f + a911094 commit 42ae345

Some content is hidden

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

65 files changed

+2130
-6
lines changed

clone-graph/Chaedie.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""
2+
한번에 풀지 못해 다시 풀어볼 예정입니다.
3+
4+
Solution:
5+
1) oldToNew 라는 dict 를 만들어 무한루프를 방지합니다.
6+
2) newNode = Node(node.val), newNode.neighbors.append(dfs(nei)) 를 통해 clone을 구현합니다.
7+
8+
정점 V, 간선 E
9+
Time: O(V + E)
10+
Space: O(V + E)
11+
"""
12+
13+
14+
class Solution:
15+
def cloneGraph(self, root: Optional["Node"]) -> Optional["Node"]:
16+
if not root:
17+
return None
18+
oldToNew = {}
19+
20+
def dfs(node):
21+
if node in oldToNew:
22+
return oldToNew[node]
23+
24+
newNode = Node(node.val)
25+
oldToNew[node] = newNode
26+
27+
for nei in node.neighbors:
28+
newNode.neighbors.append(dfs(nei))
29+
30+
return newNode
31+
32+
return dfs(root)

clone-graph/EcoFriendlyAppleSu.kt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package leetcode_study
2+
3+
/*
4+
* Graph Node 복사 문제
5+
* queue를 사용해 문제 해결
6+
* 새로 생성한 Node에 대해 방문처리를 하지 않을 경우 무한 Loop에 빠지게됨 -> 각 노드가 양방향을 가리키고 있기 때문.
7+
* 따라서, Map 자료구조를 사용해 Map<기존 Node, 복사 Node>의 모습으로 Key-Value 쌍으로 방문처리를 표현
8+
*
9+
* 시간 복잡도: O(n)
10+
* -> graph의 Node를 한 번씩 방문하여 복사하는 과정: O(n)
11+
* 공간 복잡도:
12+
* -> 복사된 Node를 매핑하는 Map 자료구조의 크기: O(n)
13+
* -> BFS를 사용한 queue size: O(n)
14+
* -> 새로 생성된 Node의 neighbor list: O(n)
15+
* */
16+
fun cloneGraph(node: Node?): Node? {
17+
if (node == null) return null
18+
if (node.neighbors.isEmpty()) return Node(1)
19+
20+
// Map< 기존 Node, 복사 Node>
21+
val nodeMap = mutableMapOf<Node, Node>()
22+
23+
val queue = ArrayDeque<Node>()
24+
queue.add(node)
25+
nodeMap[node] = Node(node.`val`)
26+
27+
while (queue.isNotEmpty()) {
28+
val current = queue.removeFirst()
29+
val clonedNode = nodeMap[current]!! // 현재 노드의 복제본
30+
31+
for (neighbor in current.neighbors) {
32+
if (neighbor == null) continue
33+
34+
// 해당 이웃이 아직 복사되지 않았다면 복사하여 맵에 저장하고 큐에 추가
35+
if (!nodeMap.containsKey(neighbor)) {
36+
nodeMap[neighbor] = Node(neighbor.`val`)
37+
queue.add(neighbor)
38+
}
39+
40+
// 복제된 현재 노드의 이웃 리스트에 복제된 이웃 노드를 추가
41+
// 양방향을 따질 필요 없이 내부 neighbor node list에 모든 노드가 있음
42+
clonedNode.neighbors.add(nodeMap[neighbor])
43+
}
44+
}
45+
return nodeMap[node]
46+
}
47+

clone-graph/dusunax.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'''
2+
# 133. Clone Graph
3+
This is the problem for copying nodes, which helps you understand the concept of referencing a node & copying the node (creating a new node from the existing one).
4+
5+
👉 Perform recursion DFS with the correct escape condition and handling of NoneType.
6+
'''
7+
8+
"""
9+
# Definition for a Node.
10+
class Node:
11+
def __init__(self, val = 0, neighbors = None):
12+
self.val = val
13+
self.neighbors = neighbors if neighbors is not None else []
14+
"""
15+
from typing import Optional
16+
class Solution:
17+
def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
18+
if node is None:
19+
return None
20+
21+
visited = {}
22+
23+
def DFS(currNode):
24+
if currNode.val in visited:
25+
return visited[currNode.val]
26+
27+
copiedNode = Node(currNode.val)
28+
visited[currNode.val] = copiedNode
29+
30+
for neighbor in currNode.neighbors:
31+
copiedNode.neighbors.append(DFS(neighbor))
32+
33+
return copiedNode
34+
35+
return DFS(node)

clone-graph/ekgns33.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
// Definition for a Node.
3+
class Node {
4+
public int val;
5+
public List<Node> neighbors;
6+
public Node() {
7+
val = 0;
8+
neighbors = new ArrayList<Node>();
9+
}
10+
public Node(int _val) {
11+
val = _val;
12+
neighbors = new ArrayList<Node>();
13+
}
14+
public Node(int _val, ArrayList<Node> _neighbors) {
15+
val = _val;
16+
neighbors = _neighbors;
17+
}
18+
}
19+
*/
20+
21+
class Solution {
22+
public Node cloneGraph(Node node) {
23+
Map<Integer, Node> nodeMap = new HashMap<>();
24+
if(node == null) return null;
25+
boolean[] visited = new boolean[101];
26+
dfsHelper(nodeMap, node, visited);
27+
return nodeMap.get(1);
28+
}
29+
30+
private void dfsHelper(Map<Integer, Node> map, Node node, boolean[] visited) {
31+
if(!map.containsKey(node.val)) {
32+
map.put(node.val, new Node(node.val));
33+
}
34+
visited[node.val] = true;
35+
Node cur = map.get(node.val);
36+
for(Node adjacent : node.neighbors) {
37+
map.putIfAbsent(adjacent.val, new Node(adjacent.val));
38+
cur.neighbors.add(map.get(adjacent.val));
39+
if(!visited[adjacent.val]) dfsHelper(map, adjacent, visited);
40+
}
41+
}
42+
}

clone-graph/imsosleepy.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// 문제 의도를 잘 모르겠음. 깊은 복사가 된 Node를 만들면 된다.
2+
// DFS로 풀면 되고, BFS도 가능하겠지만 BFS는 까딱 잘못하면 타임아웃이 나서 그냥 DFS로 해결
3+
class Solution {
4+
private Map<Node, Node> visited = new HashMap<>();
5+
6+
public Node cloneGraph(Node node) {
7+
if (node == null) return null;
8+
9+
if (visited.containsKey(node)) {
10+
return visited.get(node);
11+
}
12+
13+
Node cloneNode = new Node(node.val);
14+
visited.put(node, cloneNode);
15+
16+
for (Node neighbor : node.neighbors) {
17+
cloneNode.neighbors.add(cloneGraph(neighbor));
18+
}
19+
20+
return cloneNode;
21+
}
22+
}

clone-graph/pmjuu.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'''
2+
시간 복잡도: O(V + E)
3+
- 그래프의 모든 노드를 한 번씩 방문해야 하므로 O(V)
4+
- 각 노드의 모든 간선을 한 번씩 탐색해야 하므로 O(E)
5+
- 따라서 전체 시간 복잡도는 O(V + E)
6+
7+
공간 복잡도: O(V + E)
8+
- 클론 노드를 저장하는 딕셔너리(clones): O(V)
9+
- BFS 탐색을 위한 큐(queue): O(V)
10+
- 복제된 그래프의 노드와 간선 저장 공간: O(V + E)
11+
'''
12+
13+
from typing import Optional
14+
from collections import deque
15+
# Definition for a Node.
16+
class Node:
17+
def __init__(self, val = 0, neighbors = None):
18+
self.val = val
19+
self.neighbors = neighbors if neighbors is not None else []
20+
21+
class Solution:
22+
def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
23+
if not node:
24+
return None
25+
26+
clones = { node.val: Node(node.val) }
27+
queue = deque([node])
28+
29+
while queue:
30+
current_node = queue.popleft()
31+
32+
for neighbor in current_node.neighbors:
33+
# add neighbors
34+
if neighbor.val not in clones.keys():
35+
queue.append(neighbor)
36+
clones[neighbor.val] = Node(neighbor.val)
37+
38+
clones[current_node.val].neighbors.append(clones[neighbor.val])
39+
40+
return clones[node.val]

clone-graph/sungjinwi.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""
2+
풀이 :
3+
재귀를 이용해서 dfs풀이
4+
node를 복제하고 노드의 이웃된 노드에 대해서 재귀함수 호출을 통해 완성한다
5+
6+
clones 딕셔너리에 이미 복사된 node들을 저장해서 이미 복제된 node에 대해
7+
함수를 호출하면 바로 return
8+
9+
노드의 수 : V(정점 : Vertex) 이웃의 수 : E(간선 : Edge)라고 할 때
10+
11+
TC : O(V + E)
12+
노드와 이웃에 대해서 순회하므로
13+
14+
SC : O(V + E)
15+
해시테이블의 크기가 노드의 수에 비례해서 커지고
16+
dfs의 호출스택은 이웃의 수만큼 쌓이므로
17+
"""
18+
19+
"""
20+
# Definition for a Node.
21+
class Node:
22+
def __init__(self, val = 0, neighbors = None):
23+
self.val = val
24+
self.neighbors = neighbors if neighbors is not None else []
25+
"""
26+
from typing import Optional
27+
28+
class Solution:
29+
def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
30+
if not node :
31+
return None
32+
33+
clones = {}
34+
35+
def dfs(node : Optional['Node']) -> Optional['Node']:
36+
if node in clones :
37+
return clones[node]
38+
clone = Node(node.val)
39+
clones[node] = clone
40+
for nei in node.neighbors :
41+
clone.neighbors.append(dfs(nei))
42+
return clone
43+
44+
return dfs(node)

clone-graph/yolophg.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Time Complexity: O(N + E) - visit each node once and for each node, we iterate through its neighbors O(E).
2+
# Space Complexity: O(N) - store a copy of each node in the hashmap O(N).
3+
4+
class Solution:
5+
def cloneGraph(self, node):
6+
if node is None:
7+
return None
8+
9+
# dictionary to keep track of cloned nodes (original -> clone)
10+
mp = {}
11+
12+
def clone(node):
13+
if node in mp:
14+
# if the node has already been cloned, return the copy
15+
return mp[node]
16+
17+
# create a new node with the same value
18+
cpy = Node(node.val)
19+
# store it in the map so don't clone it again
20+
mp[node] = cpy
21+
22+
# clone all neighbors and add them to the new node's neighbors list
23+
for n in node.neighbors:
24+
cpy.neighbors.append(clone(n))
25+
26+
return cpy
27+
28+
return clone(node)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""
2+
Constraints:
3+
- n == nums.length
4+
- 1 <= n <= 5000
5+
- -5000 <= nums[i] <= 5000
6+
- All the integers of nums are unique.
7+
- nums is sorted and rotated between 1 and n times.
8+
9+
Time Complexity: O(log n)
10+
- 이진 탐색을 사용하므로 매 단계마다 탐색 범위가 절반으로 줄어듦
11+
12+
Space Complexity: O(1)
13+
- 추가 공간을 사용하지 않고 포인터만 사용
14+
15+
풀이방법:
16+
1. 이진 탐색(Binary Search) 활용
17+
2. mid와 right 값을 비교하여 조건을 나눔
18+
- Case 1: nums[mid] > nums[right]
19+
- 오른쪽 부분이 정렬되어 있지 않음
20+
- 최솟값은 mid 오른쪽에 존재
21+
- left = mid + 1
22+
- Case 2: nums[mid] <= nums[right]
23+
- mid부터 right까지는 정렬되어 있음
24+
- 최솟값은 mid를 포함한 왼쪽에 존재 가능
25+
- right = mid
26+
"""
27+
28+
class Solution:
29+
def findMin(self, nums: List[int]) -> int:
30+
left = 0
31+
right = len(nums) - 1
32+
33+
while left < right:
34+
mid = (left + right) // 2
35+
36+
if nums[mid] > nums[right]:
37+
left = mid + 1
38+
39+
else:
40+
right = mid
41+
42+
return nums[left]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Time complexity: O(logn)
2+
// Space complexity: O(1)
3+
4+
/**
5+
* @param {number[]} nums
6+
* @return {number}
7+
*/
8+
var findMin = function (nums) {
9+
let left = 0;
10+
let right = nums.length - 1;
11+
12+
while (left < right) {
13+
const mid = Math.floor((left + right) / 2);
14+
15+
if (nums.at(mid - 1) > nums.at(mid)) {
16+
return nums[mid];
17+
}
18+
19+
if (nums.at(mid + 1) < nums.at(mid)) {
20+
return nums[mid + 1];
21+
}
22+
23+
if (nums.at(mid + 1) > nums.at(right)) {
24+
left = mid + 1;
25+
continue;
26+
}
27+
28+
right = mid - 1;
29+
}
30+
31+
return nums[left];
32+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @param {number[]} nums
3+
* @return {number}
4+
*/
5+
var findMin = function (nums) {
6+
while (1 < nums.length) {
7+
8+
const mid = Math.floor(nums.length / 2);
9+
10+
const firstToHalf = [...nums].slice(0, mid);
11+
12+
const midToEnd = [...nums].slice(mid, nums.length);
13+
14+
const isInFront = Math.min(...firstToHalf) < Math.min(...midToEnd);
15+
16+
nums = isInFront ? firstToHalf : midToEnd;
17+
}
18+
19+
return nums[0];
20+
};
21+
22+
// 시간복잡도 0(logn) -> 이진탐색을 통해 배열 nums를 반으로 쪼개가며 해답을 찾기때문에
23+
// 공간복잡도 O(n) -> 처음 while문이 돌 때, nums를 쪼갠 두 배열 총 길이의 합은 nums의 처음 길이와 같기때문에

0 commit comments

Comments
 (0)