TIL/알고리즘 공부
프로그래머스 Lv. 2 Swift 알고리즘 - 메뉴 리뉴얼
여의도사노비
2023. 1. 28. 21:05
728x90
못 풀었다...
이건 그냥 못 풀었다 ㅠㅠ
다른 분들의 글을 참고해보니 DFS, Combination 등등 비슷한 맥락이지만 각자만의 방식대로 풀이가 있었다.
그중 내가 가장 인상깊게 본 코드는 아래 블로그를 운영하신 분의 코드다... 다른 코드들이 굉장히 긴 코드들이 많았는데 이 분의 코드는 엄청나게 정갈하다..! 그리고 뭔가 클로져를 팍팍 쓰신 것이... 클로져 달인이신 느낌을 받았다.
이 문제는 표시해놓고 꼭 다시 한 번 복습해야겠다!
이 문제를 풀면서 생각한 논리적 흐름
- 처음 문제를 풀때 각 코스 가짓수에 포함되는 유저의 메뉴들 중 가장 많은 수가 나온 Alphabet들을 활용해주면 되겠구나..! 라는 생각으로 시작했다.
- 하지만 막상 코드를 짜면서 생각해보니 원소의 조합이 중요했다. 단지 많이 등장한 알파벳이 아니라 이 알파벳과 저 알파벳이 서로 같은 원소 자리에 있어야 인정받을 수 있다는 것...!
- 그래서 결국 course의 메뉴 개수(ex. 2, 3, 4)를 기준으로 조합의 케이스를 전부 구한 뒤
- 그 조합 케이스가 몇번 동일하게 반복되는지 확인하고 가장 많이 반복된 케이스를 배열에 담아주면 된다.
- 논리는 간단한데 문제 풀이는 간단하지 않다 ㅠ 이게 정말 세심하게 챙겨야할 조건들이 많아서 꼼꼼하게 봐야할 듯!
* 짜다만 코드...
import Foundation
func solution(_ orders:[String], _ course:[Int]) -> [String] {
let alphabet = (97...122).map({Character(UnicodeScalar($0)).uppercased()})
var arr = Array(repeating: [Character](), count: orders.count)
var dict: [Character: Int] = [:]
// 기본세팅: 각 유저들이 선택한 메뉴 저장하기
for i in 0..<orders.count {
for j in orders[i] {
arr[i].append(j)
}
}
for menu in course {
// 기본세팅: 메뉴가 각각 몇번 나왔는지 확인
for j in alphabet {
dict[Character(j)] = 0
}
for user in arr {
if user.count >= menu {
for selectedMenu in user {
dict[selectedMenu]! += 1
}
}
}
print("\(menu)코스: \(dict.sorted {$0.0 < $1.0})")
}
return []
}
* 참고한 코드
func combination(_ str: String, len: Int) -> [String] {
if str.count < len {
return []
}
if len == 1 {
return str.map { String($0) }
}
guard let first = str.first else { return []}
let newString = String(str.dropFirst())
let c = String(first)
return combination(newString, len: len)
+ combination(newString, len: len - 1).map { c + $0 }
}
func solution(_ orders:[String], _ course:[Int]) -> [String] {
let ret = course.map { num -> [String] in
let counts = orders
.map { combination($0, len: num) }
.flatMap { $0 }
.map { $0.sorted().map{ String($0) }.joined() }
.reduce(into: [:], { counts, word in
counts[word, default: 0] += 1
})
guard let max = counts.values.max(), max >= 2
else { return [] }
let keys = counts.filter { $0.value == max }
.map { $0.key }
return keys
}
return ret.joined().sorted()
}
정리(Today I Learned)
1. 재귀를 사용할 때 나오는 return이 너무 헷갈린다. 단지 마지막에 특정 값을 반환하는게 아니라 특정 메서드를 그대로 다시 return 해주다 보니 결국 마지막에 어떤 값들이, 그리고 그 중간 중간 발생한 브랜치의 메서드 리턴값들이 어떻게 나올지 잘 감이 안온다. Combination 관련된 알고리즘 문제는 조금 더 복습을 많이 해야할 것 같다.