Skip to content
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

[똘치] Week2 #711

Merged
merged 6 commits into from
Dec 19, 2024
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
46 changes: 46 additions & 0 deletions 3sum/easyone-jwlee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 풀이
// 배열을 정렬하고
// two pointer 사용

// TC
// 정렬 O(nlogn) + Two pointer 이중 루프 O(n^2) = O(n^2)

// SC
// Go의 sort.Ints()는 TimSort를 사용.
// Merge Sort와 Insertion Sort의 조합으로 동작.
// 정렬 O(n) + Two pointer O(1) + 결과 배열 O(n) = O(n)

func threeSum(nums []int) [][]int {
result := [][]int{}
sort.Ints(nums) // nums를 정렬

for i := 0; i < len(nums)-2; i++ {
if i > 0 && nums[i] == nums[i-1] {
continue // 중복된 값 건너뜀
}

left, right := i+1, len(nums)-1
for left < right {
sum := nums[i] + nums[left] + nums[right]
if sum == 0 {
result = append(result, []int{nums[i], nums[left], nums[right]})
left++
right--

// 중복 제거
for left < right && nums[left] == nums[left-1] {
left++
}
for left < right && nums[right] == nums[right+1] {
right--
}
} else if sum < 0 {
left++
} else {
right--
}
}
}

return result
}
23 changes: 23 additions & 0 deletions climbing-stairs/easyone-jwlee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 풀이
// 1 일 때, 가능한 step은 1 -> 1가지
// 2 일 때, 가능한 step은 1 1, 2 -> 2가지
// 3 일 때, 가능한 step은 1 1 1, 1 2, 2 1 -> 3가지
// n 일 때, 가능한 stop은 n-1의 가짓수에 1이 붙고, n-2의 가짓수에 2가 붙는다.

// TC
// O(n)

// SC
// int타입 변수만 사용해서 O(1)

func climbStairs(n int) int {
if n <= 2 {
return n
}
prev := 1 // climb1
curr := 2 // climb2
for i := 3; i <= n; i++ {
prev, curr = curr, (curr + prev)
}
return curr
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 풀이
// preorder[0]이 제일 꼭대기
// preorder 배열의 root index, inorder 배열의 시작, inorder 배열의 끝
// 위의 세가지를 parameter로 받는 재귀함수를 만들어서
// 왼쪽 서브트리, 오른쪽 서브트리를 순회

// TC
// map 만들기 O(n) + 재귀함수는 각 노드를 딱 한번씩만 방문하므로 O(n) = O(n)

// SC
// map O(n) + 재귀함수 최악의 경우 한쪽으로만 노드가 이어지는 경우 O(n) = O(n)

func buildTree(preorder []int, inorder []int) *TreeNode {
inorderMap := make(map[int]int)
for i, n := range inorder {
inorderMap[n] = i
}

var recursive func(rootIndex, inStart, inEnd int) *TreeNode
recursive = func(rootIndex, inStart, inEnd int) *TreeNode {
Comment on lines +19 to +20
Copy link
Contributor

Choose a reason for hiding this comment

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

처음 Go로 문제 풀어볼 당시에 closure 함수를 어떻게 선언해야 하지.. 고민이 많았는데 잘 구현하셨네요 ㅎㅎ
혹시 Go를 현업에서 쓰고 계신가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

네 현업에서 Go를 사용해서 개발하고 있습니다. 연차에 비해 알고리즘 실력이 좋지 못해서 부단히 노력중입니다;;^ㅡ^

if rootIndex >= len(preorder) || inStart > inEnd {
return nil
}
rootVal := preorder[rootIndex]
rootInorderIndex := inorderMap[rootVal]

result := &TreeNode{
Val: rootVal,
}

leftSize := rootInorderIndex - inStart

result.Left = recursive(rootIndex+1, inStart, rootInorderIndex-1)
result.Right = recursive(rootIndex+1+leftSize, rootInorderIndex+1, inEnd)

return result
}

return recursive(0, 0, len(inorder)-1)
}
33 changes: 33 additions & 0 deletions decode-ways/easyone-jwlee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 풀이
// dp로 풀이
// 두자리 수에 적합하면 prev2(i-2)에 해당하는 값을 더하기

// TC
// O(n)

// SC
// data type이 int인 변수만 사용했으므로 O(1)
Copy link
Contributor

@obzva obzva Dec 19, 2024

Choose a reason for hiding this comment

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

사소한 피드백입니다 :)
제 생각엔 조금 더 정확한 표현을 하자면 아래처럼 쓰는게 더 맞을 것 같아요

Suggested change
// data type이 int인 변수만 사용했으므로 O(1)
// 해당 알고리즘의 추가적인 공간 사용량은 n에 상관 없이 일정하므로 O(1) (n: input으로 주어진 string `s`의 길이)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

피드백 감사합니다. 앞으로는 좀 더 정확한 표현으로 적어보겠습니다^ㅡ^


func numDecodings(s string) int {
if len(s) == 0 || s[0] == '0' {
return 0
}
prev2, prev1 := 1, 1
for i := 1; i < len(s); i++ {
curr := 0

// 한자리수 확인
if s[i] != '0' {
curr += prev1
}

// 두자리수 확인
digit, _ := strconv.Atoi(s[i-1 : i+1])
if digit >= 10 && digit <= 26 {
curr += prev2
}

prev2, prev1 = prev1, curr
}
return prev1
}
27 changes: 27 additions & 0 deletions valid-anagram/easyone-jwlee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 풀이
// s의 rune을 key로 같은 철자의 갯수를 담게하고
// t와 비교하면서 갯수를 하나씩 감소하게 해서
// 남은 철자가 있거나 (s에는 있고, r에는 없는 철자가 있는 경우)
// 더 감소된 철자가 있으면 (s에는 없고, r에만 있는 철자가 있는 경우) false가 return 되게 함.

// TC
// O(n+n+n) = O(n)

// SC
// s의 길이만큼 늘어나는 map으로 인해 O(n)

func isAnagram(s string, t string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

anagram의 속성을 이용하여 앞단에서 false를 더 빠르게 반환하는 로직이 추가되면 더 좋을 것 같아요 :)
가령 인풋으로 아래와 같은 string들이 주어지면 map 관련 연산을 하는데 불필요한 시간이 많이 들거든요

s = "aaa...aaa"   (길이 5 * 10^4)
r = "bbb...bbb"  (길이 5 * 10^4)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오 그 생각을 못했네요. 감사합니다.

m := make(map[rune]int)
for _, r := range s {
m[r]++
}
for _, r := range t {
m[r]--
}
for _, count := range m {
if count < 0 || count > 0 {
return false
}
}
return true
}
Loading