From 93e3a0d08eb4e2981e641748601c7e3c7137bd93 Mon Sep 17 00:00:00 2001 From: Invidam Date: Sun, 30 Jun 2024 09:08:07 +0900 Subject: [PATCH 1/2] solve: week 09 --- clone-graph/invidam.go.md | 33 ++++++++++ course-schedule/invidam.go.md | 45 ++++++++++++++ .../invidam.go.md | 61 +++++++++++++++++++ number-of-islands/invidam.go.md | 46 ++++++++++++++ pacific-atlantic-water-flow/invidam.go.md | 61 +++++++++++++++++++ 5 files changed, 246 insertions(+) create mode 100644 clone-graph/invidam.go.md create mode 100644 course-schedule/invidam.go.md create mode 100644 design-add-and-search-words-data-structure/invidam.go.md create mode 100644 number-of-islands/invidam.go.md create mode 100644 pacific-atlantic-water-flow/invidam.go.md diff --git a/clone-graph/invidam.go.md b/clone-graph/invidam.go.md new file mode 100644 index 000000000..8909812c8 --- /dev/null +++ b/clone-graph/invidam.go.md @@ -0,0 +1,33 @@ +# Complexity +- Time Complexity: $O(V+E)$ + - 정점의 수 V와 간선의 수 E에 대해, 모든 정점의 수 만큼 재귀호출이 일어거나 모든 간선의 수 만큼 반복문이 실행되므로 `V+E` 이다. +- Space Complexity: $O(V+E)$ + - 정점의 수 V와 간선의 수 E에 대해, 모든 정점의 수 만큼 복제본들을 저장하는 배열(`copied`)가 선언되고 모든 간선의 수 만큼 배열(`Neighbors`)가 선언되므로 `V+E` 이다. + +# Code +```go +func deepCopy(node *Node, copied map[int]*Node) *Node { + if node == nil { + return nil + } + copied[node.Val] = &Node{ + Val: node.Val, + Neighbors: make([]*Node, len(node.Neighbors)), + } + + for i := 0; i < len(node.Neighbors); i++ { + if c, found := copied[node.Neighbors[i].Val]; found { + copied[node.Val].Neighbors[i] = c + continue + } + copied[node.Val].Neighbors[i] = deepCopy(node.Neighbors[i], copied) + } + + return copied[node.Val] +} + +func cloneGraph(node *Node) *Node { + return deepCopy(node, make(map[int]*Node, 0)) +} + +``` \ No newline at end of file diff --git a/course-schedule/invidam.go.md b/course-schedule/invidam.go.md new file mode 100644 index 000000000..4af431491 --- /dev/null +++ b/course-schedule/invidam.go.md @@ -0,0 +1,45 @@ +# Complexity +- Time Complexity: $O(R*C)$ + - 정점 수와 간선 수인 V와 E에 대해, dfs인 `hasCycle`을 모두 호출하는 데 비용 V가 발생하고 반복문을 모두 순회하는 데 비용 E가 발생하여 총 비용 `V+E`가 발생한다. +- Space Complexity: $O(V+E)$ + - 정점 수와 간선 수인 V와 E에 대해, 인접 리스트 `adj`을 선언하는 데 비용 `V+E`가 발생한다. + +# Code +```go +func hasCycle(curr int, adj [][]int, visited []bool, finish []bool) bool { + if visited[curr] { + return !finish[curr] + } + visited[curr] = true + + for _, next := range adj[curr] { + if hasCycle(next, adj, visited, finish) { + return true + } + } + finish[curr] = true + + return false +} + +func canFinish(numCourses int, prerequisites [][]int) bool { + adj := make([][]int, numCourses) + for i, _ := range adj { + adj[i] = make([]int, 0) + } + for _, prerequisite := range prerequisites { + from, to := prerequisite[0], prerequisite[1] + adj[from] = append(adj[from], to) + } + + visited := make([]bool, numCourses) + finish := make([]bool, numCourses) + for from := range adj { + if hasCycle(from, adj, visited, finish) { + return false + } + } + return true +} + +``` \ No newline at end of file diff --git a/design-add-and-search-words-data-structure/invidam.go.md b/design-add-and-search-words-data-structure/invidam.go.md new file mode 100644 index 000000000..2e234f810 --- /dev/null +++ b/design-add-and-search-words-data-structure/invidam.go.md @@ -0,0 +1,61 @@ +# Complexity +- AddWord + - Time Complexity: $O(n)$ + - 단어의 길이 n만큼 재귀호출이 일어난다. + - Space Complexity: $O(n)$ + - 단어의 길이 n만큼 재귀호출이 일어난다. +- Search + - Time Complexity: $O(n)$ + - 단어의 길이 n만큼 재귀호출이 일어난다. + - Space Complexity: $O(n)$ + - 단어의 길이 n만큼 재귀호출이 일어난다. + - `.`의 개수, 단어의 범위는 모두 2, 26개로 상수개라 제외했다. + + +# Code + +```go +type WordDictionary struct { + Nodes []*WordDictionary + IsTerminated bool +} + +func Constructor() WordDictionary { + return WordDictionary{Nodes: make([]*WordDictionary, 26)} +} + +func (this *WordDictionary) AddWord(word string) { + if len(word) == 0 { + this.IsTerminated = true + return + } + + if this.Nodes[word[0]-'a'] == nil { + newNode := Constructor() + this.Nodes[word[0]-'a'] = &newNode + + } + this.Nodes[word[0]-'a'].AddWord(word[1:]) +} + +func (this *WordDictionary) Search(word string) bool { + if len(word) == 0 { + return this.IsTerminated + } + + if word[0] == '.' { + for c := 'a'; c <= 'z'; c++ { + if this.Search(string(c) + word[1:]) { + return true + } + } + return false + } + + if this.Nodes[word[0]-'a'] == nil { + return false + } + return this.Nodes[word[0]-'a'].Search(word[1:]) +} + +``` \ No newline at end of file diff --git a/number-of-islands/invidam.go.md b/number-of-islands/invidam.go.md new file mode 100644 index 000000000..7c9a6bcd1 --- /dev/null +++ b/number-of-islands/invidam.go.md @@ -0,0 +1,46 @@ +# Complexity +- Time Complexity: $O(M*N)$ + - 모든 섬을 방문하는 경우가 최대이며, 이 때 `grid`의 행의 길이인 M, 열의 길이인 N을 곱한 M*N만큼 재귀호출이 일어난다. +- Space Complexity: $O(M*N)$ + - 모든 섬의 방문 여부를 저장하기 위해 `grid`의 행의 길이인 M, 열의 길이인 N을 곱한 M*N 크기의 `visited` 배열을 선언했다. + +# Code +```go +var offsets = [][]int{ + {1, 0}, + {-1, 0}, + {0, 1}, + {0, -1}, +} + +func update(i int, j int, grid [][]byte, visited [][]bool) { + visited[i][j] = true + for _, offset := range offsets { + ni, nj := i+offset[0], j+offset[1] + if ni < 0 || ni >= len(grid) || nj < 0 || nj >= len(grid[0]) || visited[ni][nj] || grid[ni][nj] == '0' { + continue + } + update(ni, nj, grid, visited) + } +} + +func numIslands(grid [][]byte) int { + visited := make([][]bool, len(grid)) + for i, _ := range visited { + visited[i] = make([]bool, len(grid[0])) + } + + var cnt int + for i, row := range grid { + for j, val := range row { + if val == '0' || visited[i][j] { + continue + } + update(i, j, grid, visited) + cnt++ + } + } + return cnt +} + +``` \ No newline at end of file diff --git a/pacific-atlantic-water-flow/invidam.go.md b/pacific-atlantic-water-flow/invidam.go.md new file mode 100644 index 000000000..78cd68778 --- /dev/null +++ b/pacific-atlantic-water-flow/invidam.go.md @@ -0,0 +1,61 @@ +# Complexity +- Time Complexity: $O(R*C)$ + - `heights`의 행과 열인 R과 C에 대해, 반복문과 DFS의 비용인 `R*C`가 발생한다. +- Space Complexity: $O(R*C)$ + - `heights`의 행과 열인 R과 C에 대해, 방문 여부를 기록하는 배열(`pacifics`, `atlantics`)의 크기 비용인 `R*C`가 발생한다. + +# Code +```go +var offsets = [][]int{ + {1, 0}, + {-1, 0}, + {0, 1}, + {0, -1}, +} + +func update(i int, j int, heights [][]int, visited [][]bool) { + visited[i][j] = true + + for _, offset := range offsets { + ni, nj := i+offset[0], j+offset[1] + + if ni < 0 || ni >= len(visited) || nj < 0 || nj >= len(visited[0]) || visited[ni][nj] || heights[i][j] > heights[ni][nj] { + continue + } + update(ni, nj, heights, visited) + } +} + +func pacificAtlantic(heights [][]int) [][]int { + parcifics := make([][]bool, len(heights)) + for i, _ := range parcifics { + parcifics[i] = make([]bool, len(heights[0])) + } + atlantics := make([][]bool, len(heights)) + for i, _ := range atlantics { + atlantics[i] = make([]bool, len(heights[0])) + } + + for i, _ := range heights { + for j, _ := range heights[0] { + if i == 0 || j == 0 { + update(i, j, heights, parcifics) + } + if i == len(heights)-1 || j == len(heights[0])-1 { + update(i, j, heights, atlantics) + } + } + } + boths := make([][]int, 0) + for i, _ := range heights { + for j, _ := range heights[0] { + if !(parcifics[i][j] && atlantics[i][j]) { + continue + } + boths = append(boths, []int{i, j}) + } + } + return boths +} + +``` \ No newline at end of file From 49ea76f229a32fbb4eed614fe78176235b21bbc5 Mon Sep 17 00:00:00 2001 From: Invidam Date: Sun, 30 Jun 2024 23:18:46 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=EC=9E=98=EB=AA=BB=20=EA=B8=B0?= =?UTF-8?q?=EC=9E=85=ED=95=9C=20=EC=8B=9C=EA=B0=84=EB=B3=B5=EC=9E=A1?= =?UTF-8?q?=EB=8F=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- course-schedule/invidam.go.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/course-schedule/invidam.go.md b/course-schedule/invidam.go.md index 4af431491..6d45ef710 100644 --- a/course-schedule/invidam.go.md +++ b/course-schedule/invidam.go.md @@ -1,5 +1,5 @@ # Complexity -- Time Complexity: $O(R*C)$ +- Time Complexity: $O(V+E)$ - 정점 수와 간선 수인 V와 E에 대해, dfs인 `hasCycle`을 모두 호출하는 데 비용 V가 발생하고 반복문을 모두 순회하는 데 비용 E가 발생하여 총 비용 `V+E`가 발생한다. - Space Complexity: $O(V+E)$ - 정점 수와 간선 수인 V와 E에 대해, 인접 리스트 `adj`을 선언하는 데 비용 `V+E`가 발생한다.