From 30318841c5b5b95691f4f36edeff0acd3700f457 Mon Sep 17 00:00:00 2001 From: Invidam Date: Tue, 21 May 2024 17:04:07 +0900 Subject: [PATCH 1/7] feat: `number-of-1-bits` --- number-of-1-bits/invidam.go.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 number-of-1-bits/invidam.go.md diff --git a/number-of-1-bits/invidam.go.md b/number-of-1-bits/invidam.go.md new file mode 100644 index 000000000..2128560a3 --- /dev/null +++ b/number-of-1-bits/invidam.go.md @@ -0,0 +1,29 @@ +# Intuition +비트 연산자를 활용하여 계산한다. +# Approach +1. `n`과 비교하기 위한 `mask`를 생성한다. +2. `mask`를 2진수 `1`, `10`, `100` 순으로 증가시킨 후 `&` 연산자를 활용해, n의 특정 비트가 `1`인지 판단한다. +3. 참인 경우 `cnt`를 증가시켜 결과를 구한다. + +# Complexity +- Time complexity: $$O(logn)$$ + +: `mask`가 있는 반복문에 의해 결정된다. `mask`는 입력으로 들어온 `n`까지 2배씩 증가하므로 $$O(logn)$$이다. +- Space complexity: $$O(1)$$ + +: 별도 자료구조를 사용하지 않는다. +# Code +``` +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 +- 고언어에서 첫 비트 연산자 활용 \ No newline at end of file From c397bed3916a254ce3c59ec808b752b29482f87f Mon Sep 17 00:00:00 2001 From: Invidam Date: Tue, 21 May 2024 17:29:03 +0900 Subject: [PATCH 2/7] feat: `counting-bits` --- counting-bits/invidam.go.md | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 counting-bits/invidam.go.md diff --git a/counting-bits/invidam.go.md b/counting-bits/invidam.go.md new file mode 100644 index 000000000..e51fb67b3 --- /dev/null +++ b/counting-bits/invidam.go.md @@ -0,0 +1,45 @@ +# Intuition + +이전 값들을 재활용한다. +# Approach + +1. 엣지 케이스는 0을 반환한다. +2. 0, 1을 미리 계산한다. +3. `>>`을 수행한 결과 + 짝/홀 여부로 인한 1을 더해서 해결해준다. +- 이진수 `1001`의 경우 `100` 계산한 결괏값에서 `1`을 더해주면 된다. +- 이진수 `1010`의 경우 `101` 계산한 결괏값에서 `0`을 더해주면 된다. + +- 솔루션 참고: `i & (i-1)` 연산을 통해 계산한다. + - 2의 제곱수인 경우 `0`이 나와 1을 더하면 된다. + - 아닌 경우는 아직은 잘 모르겠다. +# Complexity +- Time complexity: $$O(n)$$ + +:`n`크기의 배열을 모두를 순회한다. +- Space complexity: $$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 +} +``` \ No newline at end of file From fd4a0a0f1fb26b82e2d419920b39bad526229033 Mon Sep 17 00:00:00 2001 From: Invidam Date: Tue, 21 May 2024 18:56:09 +0900 Subject: [PATCH 3/7] feat: `missing-number` --- missing-number/invidam.go.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 missing-number/invidam.go.md diff --git a/missing-number/invidam.go.md b/missing-number/invidam.go.md new file mode 100644 index 000000000..940e203ca --- /dev/null +++ b/missing-number/invidam.go.md @@ -0,0 +1,32 @@ +# Intuition + +배타적인 경우에만 참을 출력하는 `XOR` 연산을 활용한다. +# Approach + +- 문제를 치환해보자. 모든 수가 2번씩 등장하고, 하나의 수만 한 번 등장한다고 하자. +- 이 경우, 모든 수들에 `^`연산을 하면 한 번 등장한 수만을 알 수 있다. +- `배열의 길이` + `인덱스`와 `해당 인덱스일 때의 원소값`들을 모두 `^`연산하면 + - 배열 + 인덱스 순회로 모든 수는 1번씩 등장한다. + - 원소값 순회로 하나의 수를 제외하곤 1번씩 등장한다. +- 한 번만 등장한 수가 missing number이다. +# Complexity +- Time complexity: $$O(n)$$ + +: 배열의 길이 `n`, 이를 순회한다. +- Space complexity: $$O(n)$$ + + : inline, 주어진 배열의 길이 `n` + + +# Code +```go +func missingNumber(nums []int) int { + num := len(nums) + + for i, n := range nums { + num ^= i + num ^= n + } + return num +} +``` \ No newline at end of file From 5dac1daf4914942049d56ae74e06aafb9a434a8c Mon Sep 17 00:00:00 2001 From: Invidam Date: Sat, 25 May 2024 11:46:26 +0900 Subject: [PATCH 4/7] feat: `missing-number` --- missing-number/invidam.go.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/missing-number/invidam.go.md b/missing-number/invidam.go.md index 940e203ca..c6f28a30b 100644 --- a/missing-number/invidam.go.md +++ b/missing-number/invidam.go.md @@ -29,4 +29,8 @@ func missingNumber(nums []int) int { } return num } -``` \ No newline at end of file +``` + +# Today I Learned +- 다른 풀이로 풀 때, `abs()`를 이용해서 해결하려고 하였는데 해당 라이브러리가 존재하지 않았다. 왜 그런지 찾아봤는데 너무 간단한 라이브러리는 철학에 안맞는다고 안넣어준다 하더라. + - 참고: https://go.dev/doc/faq#x_in_std \ No newline at end of file From 7265665a386394682b706f77ca3a20d18cc954d2 Mon Sep 17 00:00:00 2001 From: Invidam Date: Sat, 25 May 2024 11:54:04 +0900 Subject: [PATCH 5/7] feat: `group-anagrams` --- group-anagrams/invidam.go.md | 87 ++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 group-anagrams/invidam.go.md diff --git a/group-anagrams/invidam.go.md b/group-anagrams/invidam.go.md new file mode 100644 index 000000000..65e86e9d4 --- /dev/null +++ b/group-anagrams/invidam.go.md @@ -0,0 +1,87 @@ +# Intuition +정렬된 문자열을 통해 그룹 여부를 쉽게 확인한다. +# Approach +1. `{정렬된 문자열, 그 문자열의 인덱스}`를 유지하는 배열을 선언한다. +2. 원본 배열을 순회하며 정렬한 결과, 인덱스를 struct로 하여 배열에 삽입한다. + - 인덱스를 유지하는 이유는 원본 배열의 문자열 값을 확인하기 위함이다. (정렬을 했기에 이렇지 않으면 확인이 어렵다.) +3. 모든 struct가 삽입된 배열을 문자열을 기준으로 정렬한다. +4. 반복문을 순회하며 `이전 문자열과 같은지` 여부를 그룹을 판단하여 인덱스들을 그루핑해 모아놓는다. +5. 그루핑한 인덱스들을 문자열(원본 문자열을 참조해서)로 치환하여 최종적으로 반환한다. +# Complexity +- Time complexity: $$O(n)$$ + +: 배열의 길이 `n`, 문자열의 길이 `k`. 문자열을 기준으로 정렬할 때 발생하는 비용이다. +- Space complexity: $$O(nk)$$ + +: 주어진 배열의 길이 `n`, 배열이 가지는 문자열의 길이 `k`, (코드로 생성하는 배열의 길이, 문자열의 크기 모두 `n`, `k`이다.) + + +# 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에서 문자열을 어떻게 비교하는지. +- 해당 문제 해결에 있어서 삽질한 것은 무엇이었는지. 앞으로 어떻게 해야 안할 수 있는지. \ No newline at end of file From 2da6d2a0357744bb9be522f9f6411a088e6a82ac Mon Sep 17 00:00:00 2001 From: Invidam Date: Sat, 25 May 2024 11:56:50 +0900 Subject: [PATCH 6/7] =?UTF-8?q?style:=20=EC=BD=94=EB=93=9C=20=EB=B8=94?= =?UTF-8?q?=EB=9F=AD=20=EC=96=B8=EC=96=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- number-of-1-bits/invidam.go.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/number-of-1-bits/invidam.go.md b/number-of-1-bits/invidam.go.md index 2128560a3..86ea04908 100644 --- a/number-of-1-bits/invidam.go.md +++ b/number-of-1-bits/invidam.go.md @@ -13,7 +13,7 @@ : 별도 자료구조를 사용하지 않는다. # Code -``` +```go func hammingWeight(n int) int { cnt := 0 for mask := 1; mask <= n; mask = mask << 1 { From 2f6391537229238c6f9fed0f7ac4ccf27f81990b Mon Sep 17 00:00:00 2001 From: Invidam Date: Sun, 26 May 2024 11:15:43 +0900 Subject: [PATCH 7/7] =?UTF-8?q?docs:=20=EC=8B=9C=EA=B0=84=EB=B3=B5?= =?UTF-8?q?=EC=9E=A1=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 --- group-anagrams/invidam.go.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/group-anagrams/invidam.go.md b/group-anagrams/invidam.go.md index 65e86e9d4..0505ee2bc 100644 --- a/group-anagrams/invidam.go.md +++ b/group-anagrams/invidam.go.md @@ -8,7 +8,7 @@ 4. 반복문을 순회하며 `이전 문자열과 같은지` 여부를 그룹을 판단하여 인덱스들을 그루핑해 모아놓는다. 5. 그루핑한 인덱스들을 문자열(원본 문자열을 참조해서)로 치환하여 최종적으로 반환한다. # Complexity -- Time complexity: $$O(n)$$ +- Time complexity: $$O(nklog(n))$$ : 배열의 길이 `n`, 문자열의 길이 `k`. 문자열을 기준으로 정렬할 때 발생하는 비용이다. - Space complexity: $$O(nk)$$