Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions clone-graph/dev-jonghoonpark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
- 문제: https://leetcode.com/problems/clone-graph/
- 풀이: https://algorithm.jonghoonpark.com/2024/02/13/leetcode-133

```java
class Solution {
public Node cloneGraph(Node node) {
return cloneGraph(new HashMap<>(), node);
}

private Node cloneGraph(Map<Integer, Node> map, Node node) {
if(node == null) {
return null;
}

if (map.containsKey(node.val)) {
return map.get(node.val);
}

Node copy = new Node(node.val);
map.put(node.val, copy);

for (int i = 0; i < node.neighbors.size(); i++) {
Node neighborNode = node.neighbors.get(i);
copy.neighbors.add(map.getOrDefault(neighborNode.val, cloneGraph(map, node.neighbors.get(i))));
}

return copy;
}
}
```

### TC, SC

node(vertex)의 수를 `V`, edge의 수를 `E` 라고 하였을 때 각 노드 마다 edge의 수만큼 반복을 해야한다.
시간 복잡도는 `O(V + E)` 이다. 공간 복잡도는 `O(V)`이다.
64 changes: 64 additions & 0 deletions course-schedule/dev-jonghoonpark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
- 문제: https://leetcode.com/problems/course-schedule/
- 풀이: https://algorithm.jonghoonpark.com/2024/03/01/leetcode-207

```java
public class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
if (prerequisites.length == 0) {
return true;
}

Map<Integer, Node> vertexMap = new HashMap<>();

for (int[] prerequisite : prerequisites) {
vertexMap.putIfAbsent(prerequisite[0], new Node(prerequisite[0]));
vertexMap.putIfAbsent(prerequisite[1], new Node(prerequisite[1]));

Node vertex1 = vertexMap.get(prerequisite[0]);
Node vertex2 = vertexMap.get(prerequisite[1]);

vertex1.edges.add(vertex2);
vertex2.reversedEdges.add(vertex1);
}

Deque<Integer> deque = new LinkedList<>();

int[] degrees = new int[numCourses];
for (int i = 0; i < degrees.length; i++) {
Node vertex = vertexMap.get(i);
if (vertex != null) {
degrees[i] = vertex.edges.size();
if (degrees[i] == 0) {
deque.addLast(i);
}
}
}

while(!deque.isEmpty()) {
int vertexId = deque.removeFirst();
Node vertex = vertexMap.get(vertexId);
for (Node node : vertex.reversedEdges) {
degrees[node.id]--;
if (degrees[node.id] == 0) {
deque.addLast(node.id);
}
}
vertexMap.remove(vertexId);
}

return vertexMap.isEmpty();
}
}

class Node {
int id;
List<Node> edges;
List<Node> reversedEdges;

public Node(int id) {
this.id = id;
edges = new ArrayList<>();
reversedEdges = new ArrayList<>();
}
}
```
198 changes: 198 additions & 0 deletions design-add-and-search-words-data-structure/dev-jonghoonpark.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오우.. 다양한 방법으로 풀어보셨군요! 브루트포스로도 풀릴거란 생각은 못해봤네요..ㅋㅋ

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

진짜 아슬아슬하게 걸치더라고요

image

아까 아침 미팅때 들어보니깐 다른 분은 실패하셨단것 같기도 하고... 👀

Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
- https://leetcode.com/problems/design-add-and-search-words-data-structure
- https://algorithm.jonghoonpark.com/2024/06/30/leetcode-211

## brute force

아슬아슬하게 통과한다.

```java
class WordDictionary {

Set<String> wordSet;

public WordDictionary() {
wordSet = new HashSet<>();
}

public void addWord(String word) {
wordSet.add(word);
}

public boolean search(String word) {
Deque<String> queue = new ArrayDeque<>();
queue.push(word);

while (queue.getFirst().contains(".")) {
String _word = queue.removeFirst();
String pre = _word.substring(0, _word.indexOf("."));
String post = _word.substring(_word.indexOf(".") + 1);

for (char c = 'a'; c <= 'z'; c++) {
queue.addLast(pre + c + post);
}
}

while (!queue.isEmpty()) {
String _word = queue.removeFirst();
if (wordSet.contains(_word)) {
return true;
}
}

return false;
}
}
```

### TC, SC

- `.` 이 없을 때
- 시간 복잡도 : `O(1)`
- 공간 복잡도 : `O(1)`
- `.` 이 있을 때
- 시간 복잡도 : `O(26^N)`
- 공간 복잡도 : `O(26^N)`
- 여기서 N은 `.` 의 수

## trie

[208. Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree/) 문제 에서 사용한 Trie 재사용.

```java
class WordDictionary {

Trie trie; // Trie 구현은 생략

public WordDictionary() {
trie = new Trie();
}

public void addWord(String word) {
trie.insert(word);
}

public boolean search(String word) {
if (word.contains(".")) {
String pre = word.substring(0, word.indexOf("."));
String post = word.substring(word.indexOf(".") + 1);

if (trie.startsWith(pre)) {
for (char c = 'a'; c <= 'z'; c++) {
if (search(pre + c + post)) {
return true;
}
}
}

return false;
}

return trie.search(word);
}


}
```

### TC, SC

입력된 문자열의 길이를 `L`, `.` 의 수를 `N` 이라고 하였을 때

addWord 메소드의 경우 시간 복잡도는 `O(L)`이다.
search 메소드의 경우 입력된 문자열의 길이를 n 이라 하였을 때 시간 복잡도는 `O(L * 26 ^ N)`이다.

공간 복잡도는 Trie 구조를 만드는데 사용된 공간이다. `insert된 문자열 길이의 평균` 를 `avg(L)`이라고 하였을 때 `O(avg(L) * 26)`이다. 26은 계수이기 때문에 생략할 수 있다.

## trie 개선

이 문제에 적합하도록 search를 수정하였다.

```java
class WordDictionary {

Trie trie;

public WordDictionary() {
trie = new Trie();
}

public void addWord(String word) {
trie.insert(word);
}

public boolean search(String word) {
return trie.search(word);
}


}

class Trie {

Node root = new Node();

public Trie() {

}

public void insert(String word) {
Node currentNode = root;
for (char c : word.toCharArray()) {
if (currentNode.nodes[c - 97] == null) {
currentNode.nodes[c - 97] = new Node();
}
currentNode = currentNode.nodes[c - 97];
}
currentNode.val = word;
}

public boolean search(String word) {
return search(root, word, 0);
}

public boolean search(Node node, String word, int index) {
if (node == null) {
return false;
}

if (node.val != null && node.val.length() == word.length()) {
return true;
}

if (index >= word.length()) {
return false;
}

char c = word.charAt(index);

if (c == '.') {
for (char _c = 'a'; _c <= 'z'; _c++) {
if (search(node.nodes[_c - 97], word, index + 1)) {
return true;
}
}
return false;
} else if (node.nodes[c - 97] == null) {
return false;
}

return search(node.nodes[c - 97], word, index + 1);
}
}

class Node {
String val;
Node[] nodes = new Node[26];
}
```

### TC, SC

입력된 문자열의 길이를 `L`, `.` 의 수를 `N` 이라고 하였을 때

addWord 메소드의 경우 시간 복잡도는 `O(L)`이다.
search 메소드의 경우 입력된 문자열의 길이를 n 이라 하였을 때 시간 복잡도는 `O(L * 26 ^ N)`이다.
개선 전과 비교해봤을 때 표기상으로는 차이가 없으나, 불필요한 과정을 제거하게되어서 시간이 매우 단축된다.
(`trie.startsWith(pre)`이 사라졌고, search의 호출 횟수가 줄어듬.)

공간 복잡도는 Trie 구조를 만드는데 사용된 공간이다. `insert된 문자열 길이의 평균` 를 `avg(L)`이라고 하였을 때 `O(avg(L) * 26)`이다. 26은 계수이기 때문에 생략할 수 있다.
40 changes: 40 additions & 0 deletions number-of-islands/dev-jonghoonpark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
- 문제: https://leetcode.com/problems/number-of-islands/
- 풀이: https://algorithm.jonghoonpark.com/2024/03/31/leetcode-200

```java
class Solution {
public int numIslands(char[][] grid) {
int w = grid.length;
int h = grid[0].length;

int count = 0;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
if (grid[i][j] == '1') {
dfs(grid, i,j);
count++;
}
}
}
return count;
}

public void dfs(char[][] grid, int i, int j) {
if(i < 0 || i >= w || j < 0 || j >= h || grid[i][j] == '0') {
return;
}

grid[i][j] = '0';

dfs(grid, i-1, j);
dfs(grid, i, j-1);
dfs(grid, i+1, j);
dfs(grid, i, j+1);
}
}
```

## TC, SC

코드에 정의한 대로 grid의 길이를 `w`, grid[0]의 길이를 `h`로 정의했을 때,
이 코드의 시간 복잡도는 O(w \* h), 공간 복잡도는 O(w \* h) 이다.
Loading