-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Vidam] Week 3 Solution | Go #81
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
11ad1cd
feat: max-depth-of-bin-tree
Invidam 3991530
docs: change word
Invidam 2a7011c
feat: solve same-tree
Invidam d77b7bf
docs: 링크 추가
Invidam 73a0495
feat: subtree-of-another-tree
Invidam 5d244b9
feat: climb-stairs 추가
Invidam 557a0f9
feat: meeting-rooms
Invidam 377bd1d
docs: til 추가
Invidam 2120a8b
style: code block `syntax` 적용
Invidam 7ae7990
style: code block `syntax` 적용
Invidam File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,83 @@ | ||
# Intuition | ||
<!-- Describe your first thoughts on how to solve this problem. --> | ||
This problem is a typical dynamic programming (DP) problem. (keyword: `Fibonacci`) | ||
|
||
DP has two methods: tabulation and memoization. I'll introduce both methods. | ||
# Approach (tabulation) | ||
<!-- Describe your approach to solving the problem. --> | ||
1. Create an array to store the results. | ||
2. Initiate default values for the base cases `0` and `1`. | ||
3. While iterating through the array, fill in the values using this formula $$f(n) = f(n-1) + f(n-2)$$ | ||
# Complexity | ||
## Complexity (V1) | ||
- Time complexity: $$O(n)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
|
||
- Space complexity: $$O(n)$$ | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
# Complexity (V2) | ||
- Time complexity: $$O(n)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
|
||
- Space complexity: $$O(1)$$ | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
|
||
(n is value of `n`) | ||
# Code | ||
```go | ||
func climbStairsV1(n int) int { | ||
climbData := make([]int, n+2, n+2) | ||
climbData[0], climbData[1] = 1, 1 | ||
for s := 0; s < n; s++ { | ||
climbData[s+2] = climbData[s] + climbData[s+1] | ||
} | ||
|
||
return climbData[n] | ||
} | ||
|
||
func climbStairsV2(n int) int { | ||
prev, curr := 1, 1 | ||
for s := 1; s < n; s++ { | ||
prev, curr = curr, prev+curr | ||
} | ||
|
||
return curr | ||
} | ||
``` | ||
|
||
> As you can see in `V2`, it can be optimized. Remove the array and maintain only the `prev` and `curr` values. In Golang, `Multiple Assignment` prodives syntatic sugar. | ||
|
||
- - - | ||
|
||
# Approach (memoization) | ||
<!-- Describe your approach to solving the problem. --> | ||
1. Create an hash map (or array) to **cache** the results. | ||
2. Initialize default values to indicate unvisited nodes. (`-1`). | ||
3. Call the recursion using this formula $$f(n) = f(n-1) + f(n-2)$$. | ||
4. If there are cached results, return it. | ||
5. Pay attension to the **base case**, and always update the cache. | ||
|
||
# Complexity | ||
- Time complexity: $$O(n)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
|
||
- Space complexity: $$O(n)$$ | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
(n is value of `n`) | ||
# Code | ||
```go | ||
var cache map[int]int = map[int]int{} | ||
func climbStairs(n int) int { | ||
if n == 0 || n == 1 { | ||
return 1 | ||
} else if n < 0 { | ||
return 0 | ||
} else if val, ok := cache[n]; ok { | ||
return val | ||
} | ||
|
||
ret := climbStairs(n-1) + climbStairs(n-2) | ||
cache[n] = ret | ||
return ret | ||
} | ||
``` |
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,75 @@ | ||
# Intuition | ||
Recursuib is a natural method for iterating trees. | ||
|
||
# Approach | ||
<!-- Describe your approach to solving the problem. --> | ||
1. Child function can calculate the depth of its subtrees automatically. | ||
2. Parent function only select the maximum of the two depths and return +1. (i.e. `+1` means parent's depth.) | ||
|
||
# Complexity | ||
- Time complexity: $$O(n)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
|
||
- Space complexity | ||
- $$O(logN)$$ (best case for balanced tree) | ||
- $$O(N)$$ (worst case for skewed tree) | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
(N: size of node.) | ||
# Code | ||
``` | ||
func maxDepth(root *TreeNode) int { | ||
if root == nil { | ||
return 0 | ||
} | ||
return max(maxDepth(root.Left), maxDepth(root.Right)) + 1 | ||
} | ||
``` | ||
- - - | ||
# Intuition | ||
Implement Queue can be troublesome, but it is effective to problem that require tracking depths or levels. | ||
<!-- Describe your first thoughts on how to solve this problem. --> | ||
|
||
# Approach | ||
<!-- Describe your approach to solving the problem. --> | ||
1. Maintain Element belonging to the same level in the queue. | ||
2. While Iterating through the queue, remove the current level and save the next level. | ||
- In GoLang, `range for loop` capture only first once. So We can maintain current level's easily. | ||
3. increase depth while iterationg through all elements until the end. | ||
# Complexity | ||
- Time complexity: $$O(n)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
|
||
- Space complexity | ||
- $$O(logN)$$ (best case for balanced tree) | ||
- $$O(N)$$ (worst case for skewed tree) | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
(N: size of node.) | ||
|
||
# Code | ||
```go | ||
func maxDepth(root *TreeNode) int { | ||
if root == nil { | ||
return 0 | ||
} | ||
depth := 0 | ||
currLevel := []*TreeNode{root} | ||
|
||
for len(currLevel) != 0 { | ||
depth++ | ||
for _, curr := range currLevel { | ||
if curr.Left != nil { | ||
currLevel = append(currLevel, curr.Left) | ||
} | ||
if curr.Right != nil { | ||
currLevel = append(currLevel, curr.Right) | ||
} | ||
currLevel = currLevel[1:] | ||
} | ||
} | ||
|
||
return depth | ||
} | ||
``` | ||
|
||
# What I learned | ||
- [Slice](https://velog.io/@invidam/GoLang-Slice) |
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,34 @@ | ||
# Intuition | ||
It is a simple `greedy` problem. | ||
간단한 그리디 분류의 문제다. | ||
# Approach | ||
1. To find earliest interval, sort intervals by start time in ascending order. | ||
2. After sorting, while iterating through the array, check for conflict: the current interval's start time shoud be smaller than the next interval's end time. | ||
# Complexity | ||
- Time complexity: $$O(nlog(n))$$ | ||
- Space complexity: $$O(n)$$ | ||
|
||
(n is length of `intervals`) | ||
# Code | ||
```go | ||
func CanAttendMeetings(intervals []*Interval) bool { | ||
sort.Slice(intervals, func(i, j int) bool { | ||
return intervals[i].Start < intervals[j].Start | ||
}) | ||
|
||
curr := &Interval{-1, -1} | ||
for _, next := range intervals { | ||
if curr.End > next.Start { | ||
return false | ||
} | ||
curr = next | ||
} | ||
|
||
return true | ||
} | ||
``` | ||
|
||
# What I learned | ||
GoLang Sort | ||
- mechanism: [Pattern-defeating Quicksort](https://www.youtube.com/watch?v=jz-PBiWwNjc) | ||
- usage: https://hackthedeveloper.com/how-to-sort-in-go/ |
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,82 @@ | ||
# Intuition (DFS, Recursion) | ||
<!-- Describe your first thoughts on how to solve this problem. --> | ||
Recursion is natural method to iterate trees. (Particularly, multiple trees!) | ||
# Approach | ||
<!-- Describe your approach to solving the problem. --> | ||
1. Child nodes(i.e. Left and Right) are compared eqaulity with their subtrees. | ||
2. Parent nodes check their own values (`Val`) and their children's comparisions. | ||
|
||
(Tip: Comparing the values of nodes before recursion is more efficient. due to **short circuit**, which stops further evaluation(`isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)`) when the outcome is already determined by comparing `p.Val == q.Val`) | ||
# Complexity | ||
- Time complexity: $$O(n+m)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
|
||
- Space complexity: $$O(h_n + h_m)$$ | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
|
||
(n and m are number of nodes in trees p and q. $$h_n$$ and $$h_m$$ are their heights.) | ||
# Code | ||
```go | ||
func isSameTree(p *TreeNode, q *TreeNode) bool { | ||
if p == nil || q == nil { | ||
return p == nil && q == nil | ||
} | ||
|
||
return p.Val == q.Val && isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right) | ||
} | ||
``` | ||
- - - | ||
# BFS | ||
# Approach | ||
<!-- Describe your approach to solving the problem. --> | ||
1. Like a typical BFS solution, Create Queue and iterate through the tree. However, in this case, mulitple queues are required. | ||
2. While Iterating, Check equality two nodes in p and q. | ||
# Complexity | ||
- Time complexity: $$O(n+m)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
|
||
- Space complexity: $$O(n + m)$$ | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
|
||
(n and m are number of nodes in trees p and q.) | ||
# Code | ||
```go | ||
func updateQueue(node *TreeNode, queue []*TreeNode) []*TreeNode { | ||
queue = append(queue, node.Left) | ||
queue = append(queue, node.Right) | ||
|
||
return queue | ||
} | ||
|
||
func isSameTree(p *TreeNode, q *TreeNode) bool { | ||
if p == nil || q == nil { | ||
return p == nil && q == nil | ||
} | ||
pQueue := []*TreeNode{p} | ||
qQueue := []*TreeNode{q} | ||
|
||
for len(pQueue) != 0 { | ||
pCurr := pQueue[0] | ||
qCurr := qQueue[0] | ||
|
||
pQueue = pQueue[1:] | ||
qQueue = qQueue[1:] | ||
|
||
if pCurr == nil && qCurr == nil { | ||
continue | ||
} | ||
|
||
if (pCurr == nil || qCurr == nil) || (pCurr.Val != qCurr.Val) { | ||
return false | ||
} | ||
pQueue = updateQueue(pCurr, pQueue) | ||
qQueue = updateQueue(qCurr, qQueue) | ||
} | ||
|
||
return true | ||
} | ||
``` | ||
|
||
# What I learned | ||
- Short circuit In Go. | ||
- Function couldn't update original value (like `updateQueue()'s queue`) |
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,105 @@ | ||
# Intuition (DFS & BFS) | ||
<!-- Describe your first thoughts on how to solve this problem. --> | ||
We need two main function: one to check the equality of nodes and the subtrees, and another to iterate through the main tree. | ||
|
||
We will use both DFS and BFS methods to solve this problem. | ||
|
||
Reference. [Same Tree](ttps://leetcode.com/problems/same-tree/solutions/5159658/go-simple-solution) | ||
|
||
# Approach | ||
<!-- Describe your approach to solving the problem. --> | ||
1. Create a function that, while iterating using DFS(Recursion) or BFS(Queue),checks if the two trees are equal. | ||
2. First, check if the two trees are equal. If not, iterate through the children of main tree. (`root.Left`, `root.Right`) | ||
# Complexity (DFS) | ||
- Time complexity: $$O(n * m)$$ | ||
(This complexity is $$O(n * m)$$. because the `isSubtree()` iterates throuth all modes while **simultaneously** calling the `isEqualtree()` for each node. | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
|
||
- Space complexity: $$O({h_n} + {h_m})$$ | ||
(This complexity is determined. because the maximun depth of the call stack, which doesn't exceed the sum of heights of both trees.) | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
|
||
# Code | ||
``` | ||
func isEqualTree(root *TreeNode, subRoot *TreeNode) bool { | ||
if (root == nil) || (subRoot == nil) { | ||
return root == subRoot | ||
} | ||
|
||
return (root.Val == subRoot.Val) && isEqualTree(root.Left, subRoot.Left) && isEqualTree(root.Right, subRoot.Right) | ||
} | ||
|
||
func isSubtree(root *TreeNode, subRoot *TreeNode) bool { | ||
if root == nil { | ||
//assert subRoot != nil | ||
return false | ||
} | ||
|
||
return isEqualTree(root, subRoot) || isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot) | ||
} | ||
``` | ||
- - - | ||
# Complexity (BFS) | ||
- Time complexity: $$O(n * m)$$ | ||
(This complexity is $$O(n * m)$$. because the `isSubtree()` iterates throuth all modes while **simultaneously** calling the `isEqualtree()` for each node. | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
|
||
- Space complexity: $$O({h_n} + {h_m})$$ | ||
(This complexity is determined. because the maximun sizes of the queues (`q`, `q1`, `q2`), which doesn't exceed the sum of sizes of both trees.) | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
# Code | ||
```go | ||
func isEqualTree(root *TreeNode, subRoot *TreeNode) bool { | ||
q1 := []*TreeNode{root} | ||
q2 := []*TreeNode{subRoot} | ||
|
||
for len(q1) != 0 { | ||
f1 := q1[0] | ||
f2 := q2[0] | ||
|
||
q1 = q1[1:] | ||
q2 = q2[1:] | ||
|
||
if (f1 == nil) && (f2 == nil) { | ||
continue | ||
} | ||
if (f1 == nil) || (f2 == nil) || (f1.Val != f2.Val) { | ||
return false | ||
} | ||
|
||
q1 = append(q1, f1.Left) | ||
q1 = append(q1, f1.Right) | ||
|
||
q2 = append(q2, f2.Left) | ||
q2 = append(q2, f2.Right) | ||
} | ||
|
||
return true | ||
} | ||
|
||
func isSubtree(root *TreeNode, subRoot *TreeNode) bool { | ||
if root == nil { | ||
//assert subRoot != nil | ||
return false | ||
} | ||
|
||
q := []*TreeNode{root} | ||
|
||
for len(q) != 0 { | ||
node := q[0] | ||
q = q[1:] | ||
|
||
if node == nil { | ||
continue | ||
} | ||
if isEqualTree(node, subRoot) { | ||
return true | ||
} | ||
|
||
q = append(q, node.Left) | ||
q = append(q, node.Right) | ||
} | ||
|
||
return false | ||
} | ||
``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다! 요 파일 제외하고 나머지 파일들은 전부 코드언어 설정을 따로 안한 상태로 업로드 하셨는데 혹시 빼먹으신게 아닌가 싶어요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그러네요!! 밑에 코멘트까지 참고하여 담주부턴 반영하겠습니다~
감사해용
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
앗 leo님이 먼저 달아주셨었군요..! 못보고 추가로 말씀드려버렸네요...! ㅠㅠ