-
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, Invidam] Week 4 Solution #92
Changes from all commits
3031884
c397bed
fd4a0a0
5dac1da
7265665
2da6d2a
2f63915
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Intuition | ||
<!-- Describe your first thoughts on how to solve this problem. --> | ||
이전 값들을 재활용한다. | ||
# Approach | ||
<!-- Describe your approach to solving the problem. --> | ||
1. 엣지 케이스는 0을 반환한다. | ||
2. 0, 1을 미리 계산한다. | ||
3. `>>`을 수행한 결과 + 짝/홀 여부로 인한 1을 더해서 해결해준다. | ||
- 이진수 `1001`의 경우 `100` 계산한 결괏값에서 `1`을 더해주면 된다. | ||
- 이진수 `1010`의 경우 `101` 계산한 결괏값에서 `0`을 더해주면 된다. | ||
|
||
- 솔루션 참고: `i & (i-1)` 연산을 통해 계산한다. | ||
- 2의 제곱수인 경우 `0`이 나와 1을 더하면 된다. | ||
- 아닌 경우는 아직은 잘 모르겠다. | ||
# Complexity | ||
- Time complexity: $$O(n)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
:`n`크기의 배열을 모두를 순회한다. | ||
- Space complexity: $$O(n)$$ | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
:크기 `n`의 배열을 선언한다. | ||
# Code | ||
```go | ||
func countBits(n int) []int { | ||
if n == 0 { | ||
return []int{0} | ||
} | ||
ans := make([]int, n+1, n+1) | ||
|
||
ans[0], ans[1] = 0, 1 | ||
|
||
for i := 2; i <= n; i++ { | ||
ans[i] = ans[i>>1] + i&1 | ||
} | ||
return ans | ||
} | ||
|
||
func countBitsSolution(n int) []int { | ||
res := make([]int, n+1) | ||
for i := 1; i <= n; i++ { | ||
res[i] = res[i&(i-1)] + 1 | ||
} | ||
return res | ||
} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# Intuition | ||
정렬된 문자열을 통해 그룹 여부를 쉽게 확인한다. | ||
# Approach | ||
1. `{정렬된 문자열, 그 문자열의 인덱스}`를 유지하는 배열을 선언한다. | ||
2. 원본 배열을 순회하며 정렬한 결과, 인덱스를 struct로 하여 배열에 삽입한다. | ||
- 인덱스를 유지하는 이유는 원본 배열의 문자열 값을 확인하기 위함이다. (정렬을 했기에 이렇지 않으면 확인이 어렵다.) | ||
3. 모든 struct가 삽입된 배열을 문자열을 기준으로 정렬한다. | ||
4. 반복문을 순회하며 `이전 문자열과 같은지` 여부를 그룹을 판단하여 인덱스들을 그루핑해 모아놓는다. | ||
5. 그루핑한 인덱스들을 문자열(원본 문자열을 참조해서)로 치환하여 최종적으로 반환한다. | ||
# Complexity | ||
- Time complexity: $$O(nklog(n))$$ | ||
<!-- Add your time complexity here, e.g. $$O(nklog(n))$$ --> | ||
: 배열의 길이 `n`, 문자열의 길이 `k`. 문자열을 기준으로 정렬할 때 발생하는 비용이다. | ||
- Space complexity: $$O(nk)$$ | ||
|
||
: 주어진 배열의 길이 `n`, 배열이 가지는 문자열의 길이 `k`, (코드로 생성하는 배열의 길이, 문자열의 크기 모두 `n`, `k`이다.) | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
|
||
# Code | ||
```go | ||
type StrAndIdx struct { | ||
Str string | ||
Idx int | ||
} | ||
|
||
func sortSring(s string) string { | ||
runes := []rune(s) | ||
|
||
sort.Slice(runes, func(i, j int) bool { | ||
return runes[i] < runes[j] | ||
}) | ||
|
||
return string(runes) | ||
} | ||
|
||
func groupAnagrams(strs []string) [][]string { | ||
|
||
strAndIdxs := make([]StrAndIdx, 0, len(strs)+5) | ||
|
||
for i, s := range strs { | ||
strAndIdxs = append(strAndIdxs, StrAndIdx{sortSring(s), i}) | ||
} | ||
|
||
sort.Slice(strAndIdxs, func(i, j int) bool { | ||
return strAndIdxs[i].Str < strAndIdxs[j].Str | ||
}) | ||
|
||
groupedIdxs := make([][]int, 0, len(strAndIdxs)/4) | ||
|
||
group := make([]int, 0) | ||
defaultString := "NOT_EXIST_STRING" | ||
prev := defaultString | ||
for _, sAI := range strAndIdxs { | ||
curr := sAI.Str | ||
idx := sAI.Idx | ||
if prev == curr { | ||
group = append(group, idx) | ||
} else { | ||
if prev != defaultString { | ||
groupedIdxs = append(groupedIdxs, group) | ||
} | ||
group = []int{idx} | ||
} | ||
prev = curr | ||
} | ||
|
||
if len(group) != 0 { | ||
groupedIdxs = append(groupedIdxs, group) | ||
} | ||
|
||
groupedStrs := make([][]string, 0, len(groupedIdxs)) | ||
for _, idxs := range groupedIdxs { | ||
|
||
groupStr := make([]string, 0, len(idxs)) | ||
for _, idx := range idxs { | ||
groupStr = append(groupStr, strs[idx]) | ||
} | ||
groupedStrs = append(groupedStrs, groupStr) | ||
} | ||
|
||
return groupedStrs | ||
} | ||
``` | ||
|
||
# **To** Learn | ||
- GoLang에서 문자열을 어떻게 비교하는지. | ||
- 해당 문제 해결에 있어서 삽질한 것은 무엇이었는지. 앞으로 어떻게 해야 안할 수 있는지. |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Go 는 약간 간단한 라이브러리가 없어서 어려운것 같아요 😱 근데 또 쓰시는 분들은 그맛 에 쓰시더라구요 어떻게 해야 bit으로 처리할 수 있을지 궁금했는데 덕분에 궁금증이 해소되었네요...! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이미 간단한 라이브러리가 없는 상황에서, 간단한 라이브러리를 추가한다는 게 생각보다 단순한 일이 아니라는 걸 배웠어요. 이미 대부분의 사람들이 간단한 라이브러리를 구현해서 사용하고 있는 와중에 추가된다면 어려움이 있겠다. 하위호환성 문제가 있겠다를 느꼈어요 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Intuition | ||
<!-- Describe your first thoughts on how to solve this problem. --> | ||
배타적인 경우에만 참을 출력하는 `XOR` 연산을 활용한다. | ||
# Approach | ||
<!-- Describe your approach to solving the problem. --> | ||
- 문제를 치환해보자. 모든 수가 2번씩 등장하고, 하나의 수만 한 번 등장한다고 하자. | ||
- 이 경우, 모든 수들에 `^`연산을 하면 한 번 등장한 수만을 알 수 있다. | ||
- `배열의 길이` + `인덱스`와 `해당 인덱스일 때의 원소값`들을 모두 `^`연산하면 | ||
- 배열 + 인덱스 순회로 모든 수는 1번씩 등장한다. | ||
- 원소값 순회로 하나의 수를 제외하곤 1번씩 등장한다. | ||
- 한 번만 등장한 수가 missing number이다. | ||
# Complexity | ||
- Time complexity: $$O(n)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
: 배열의 길이 `n`, 이를 순회한다. | ||
- Space complexity: $$O(n)$$ | ||
|
||
: inline, 주어진 배열의 길이 `n` | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
|
||
# Code | ||
```go | ||
func missingNumber(nums []int) int { | ||
num := len(nums) | ||
|
||
for i, n := range nums { | ||
num ^= i | ||
num ^= n | ||
} | ||
return num | ||
} | ||
``` | ||
|
||
# Today I Learned | ||
- 다른 풀이로 풀 때, `abs()`를 이용해서 해결하려고 하였는데 해당 라이브러리가 존재하지 않았다. 왜 그런지 찾아봤는데 너무 간단한 라이브러리는 철학에 안맞는다고 안넣어준다 하더라. | ||
- 참고: https://go.dev/doc/faq#x_in_std | ||
Comment on lines
+34
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Go의 철학이 돋보이는 대목이네요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다행히? 작년(1.21) 부터는 생겼네요! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Intuition | ||
비트 연산자를 활용하여 계산한다. | ||
# Approach | ||
1. `n`과 비교하기 위한 `mask`를 생성한다. | ||
2. `mask`를 2진수 `1`, `10`, `100` 순으로 증가시킨 후 `&` 연산자를 활용해, n의 특정 비트가 `1`인지 판단한다. | ||
3. 참인 경우 `cnt`를 증가시켜 결과를 구한다. | ||
|
||
# Complexity | ||
- Time complexity: $$O(logn)$$ | ||
<!-- Add your time complexity here, e.g. $$O(n)$$ --> | ||
: `mask`가 있는 반복문에 의해 결정된다. `mask`는 입력으로 들어온 `n`까지 2배씩 증가하므로 $$O(logn)$$이다. | ||
- Space complexity: $$O(1)$$ | ||
<!-- Add your space complexity here, e.g. $$O(n)$$ --> | ||
: 별도 자료구조를 사용하지 않는다. | ||
# Code | ||
```go | ||
func hammingWeight(n int) int { | ||
cnt := 0 | ||
for mask := 1; mask <= n; mask = mask << 1 { | ||
if (mask & n) != 0 { | ||
cnt += 1 | ||
} | ||
} | ||
return cnt | ||
} | ||
``` | ||
|
||
# What I learned | ||
- 고언어에서 첫 비트 연산자 활용 |
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.
어떻게 O(n)으로 이 문제를 해결할 수 있을지 궁금하긴한데
코드 양이 헉소리가 나오군요 ; )
시간날 때 구경해봐야겠습니다.
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.
헉.. 실수로 주석에다가 시간복잡도를 변경했어요$O(n)$ 이 아닙니다..ㅠ
정렬비용이 있어
앞으론 꼼꼼히 보겠습니다! ㅋㅋㅋㅋㅋ