Skip to content

[JustHm] Week 02 solutions #1205

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

Merged
merged 6 commits into from
Apr 12, 2025
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
28 changes: 28 additions & 0 deletions 3sum/JustHm.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class Solution {
// time: O(n2) space: O(n)..?
func threeSum(_ nums: [Int]) -> [[Int]] {
let nums = nums.sorted() // hashmap 방식으로는 안될거 같아 정렬후 순차탐색 하기

var answer = Set<[Int]>() // 중복 제거를 위해 Set으로 선언
for i in nums.indices {
var left = i + 1
var right = nums.count - 1
while left < right {
let result = nums[left] + nums[right] + nums[i]
if result == 0 {
answer.insert([nums[i], nums[left], nums[right]])
// 포인터 옮겨주고 더 검사하기
right -= 1
left += 1
}
else if result > 0 {
right -= 1
}
else {
left += 1
}
}
}
return Array(answer)
}
}
47 changes: 47 additions & 0 deletions climbing-stairs/JustHm.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
class Solution {
func climbStairs(_ n: Int) -> Int {
var arr = [1, 2, 3, 5, 8]
if arr.count > n { return arr[n-1] }

for i in 4..<n {
arr.append(arr[i] + arr[i-1])
}
return arr[n-1]
}
}

/*
규칙 찾기
1
1

2
1 1
2

3
1 1 1
1 2
2 1

4
1 1 1 1
1 1 2
1 2 1
2 1 1
2 2

5
1 1 1 1 1
1 1 1 2
1 1 2 1
1 2 1 1
2 1 1 1
1 2 2
2 1 2
2 2 1

1 2 3 5 8

이전 두 결과값을 더한게 다음 결과값임
*/
50 changes: 50 additions & 0 deletions product-of-array-except-self/JustHm.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
class Solution {
// time: O(n), space: O(n)
func productExceptSelf(_ nums: [Int]) -> [Int] {
var resultFromFirst = [1]
var resultFromLast = [1]
// 기준 원소의 왼쪽 곱은 resultFromFirst에 저장
// 기준 원소의 오른쪽 곱은 resultFromLast에 저장
for i in 1..<nums.count {
resultFromFirst.append(resultFromFirst[i-1] * nums[i-1])
resultFromLast.append(resultFromLast[i-1] * nums[nums.count - i])
}
// 결과 반환시 순서를 생각해서
//resultFromFirst는 첫번째 원소부터 마지막 원소까지, resultFromLast는 마지막 원소 부터 첫번째 원소까지, 서로를 곱해준다.
return (0..<nums.count).map { resultFromFirst[$0] * resultFromLast[nums.count - $0 - 1] }
}
}
//Input: nums = [1,2,3,4]
//Output: [24,12,8,6]
/*
2*3*4, 3*4, 4, 1 오른쪽 부분 곱
1, 1, 1*2, 1*2*3 왼쪽 부분 곱
*/

// 공간 복잡도를 O(1)로도 해결이 가능하다! (결과배열 제외)
// 아이디어를 생각해보자.
/*
1. 결과 배열을 하나 만든다.
2. nums의 원소들을 사용해 왼쪽부분 곱을 먼저 결과배열에 저장한다.
3. 오른쪽 부분 곱을 차례대로 계산에 결과배열 원소에 곱연산해 저장한다.
4. 반환!
*/
class Solution {
func productExceptSelf(_ nums: [Int]) -> [Int] {
var result = Array(repeating: 1, count: nums.count)
for i in 1..<nums.count {
// 원래 하던대로 왼쪽 부분 곱으로 초기화
result[i] = result[i-1] * nums[i-1]
}

var temp = 1 // 오른쪽 곱 값을 저장해 둘 변수
for i in 1...nums.count {
// 결과 배열의 마지막 부터 self 의 오른쪽 부분 곱 시작
result[nums.count - i] *= temp
// 연산 후 temp에 nums의 오른쪽 원소 하나씩 곱하기
temp *= nums[nums.count - i]
}

return result
}
}
47 changes: 47 additions & 0 deletions valid-anagram/JustHm.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
class Solution {
func isAnagram(_ s: String, _ t: String) -> Bool { // O(n)
// s 문자열의 문자를 키로 빈도수를 값으로 저장
var baseDict = Dictionary(s.map{($0,1)}, uniquingKeysWith: +)

for char in t { // t를 반복하면서 존재하는지 확인, 만약 없다면 return false
guard baseDict[char] != nil, baseDict[char] != 0
else { return false }

baseDict[char]? -= 1
if baseDict[char] == 0 {
baseDict.removeValue(forKey: char)
}
}
return baseDict.isEmpty
}
}

// MARK: 가장 간단한 방법 time: O(nlogn)
class Solution2 {
func isAnagram(_ s: String, _ t: String) -> Bool {
s.sorted() == t.sorted()
}
}

// MARK: 실행속도가 가장 빠름 time: O(n)
class Solution3 {
func isAnagram(_ s: String, _ t: String) -> Bool {
guard s.count == t.count else { return false }

let sCharCount = getCharacterCount(s)
let tCharCount = getCharacterCount(t)
// 반환된 배열이 동일하면 애너그램
return sCharCount == tCharCount
}
// 배열로 문자 빈도수를 처리 및 저장
private func getCharacterCount(_ str: String) -> [Int] {
var charCount = [Int](repeating: 0, count: 26)
let aAsciiValue = Character("a").asciiValue ?? 0

for char in str.utf8 {
charCount[Int(char - aAsciiValue)] += 1
}

return charCount
}
}
Copy link
Contributor

@ayosecu ayosecu Apr 6, 2025

Choose a reason for hiding this comment

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

저는 Swift 언어를 다룬 적이 없지만, 세가지 방법으로 구현하신 것 같습니다.

  1. Dictionary 를 이용하여 문자별로 count 를 세고, 체크 (없으면 False, 있으면 감소 시키고, 최종 empty 인지 체크)
  2. sort 를 이용하여 같은지 비교
  3. Counter 구현 (Char key 가 아닌 26 size 의 integer 배열 이용)

다양한 방법으로 구현하신 것을 보고, python 의 Counter 를 이용해서 딸랑 한개의 메소드만을 구현한 제 자신을 반성하게 되었습니다. 😭
속도와 구현 난이도를 구별해주신 부분도 좋았습니다.
다만, 속도 비교의 경우 알고리즘에서는 Big O 표기법이 표준(?) 으로 인식 되는 만큼 Big O 표기법을 이용해서 시간/공간 복잡도를 작성(노트)해보신다면, 추후 인터뷰에 도움이 될 것 같다는 생각을 해봅니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

리뷰 감사합니다! 시간복잡도 생각해서 메모해두는것도 좋겠네요.. 습관을 좀 들여야겠습니다 ㅎㅎ

17 changes: 17 additions & 0 deletions validate-binary-search-tree/JustHm.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// time: O(n)
class Solution {
func isValidBST(_ root: TreeNode?) -> Bool {
return checkNodes(root, Int.min, Int.max)
}

func checkNodes(_ root: TreeNode?, _ min: Int, _ max: Int) -> Bool {
guard let node = root else { return true }
if node.val <= min || node.val >= max { return false }

return checkNodes(node.left, min, node.val) && checkNodes(node.right, node.val, max)
}
}
/*
중위순회를 통해서도 해결이 가능하다.
중위순회를 하며 이전에 들렀던 값보다 현재 방문한 노드의 값이 작으면 false!
*/