오늘의 문제: 25757
민겸이는 친구들과 함께 Y, F, O 세 가지 게임을 하려고 한다. 각 게임별로 필요한 참가자 수가 다르며, 이미 게임을 한 사람과는 다시 게임을 하지 않는다.
이 문제는 N명의 사람들과 게임 종류(Y, F, O)가 주어질 때, 민겸이가 몇 번의 게임을 할 수 있는지 계산하는 문제이다.
처음에는 게임 종류별 필요 인원 수를 다음과 같이 설정했다:
하지만 처음 접근에서 실수했던 부분은 민겸이를 포함한 인원 수를 계산했다는 점이다. 민겸이는 항상 참여하므로 추가로 필요한 인원은 각각 1명, 2명, 3명이었다.
// 초기 접근 (오류)
init(game: String) {
let game = Game(rawValue: game)!
self.capacity = game.capacity
}
핵심 아이디어는 다음과 같다:
1. 각 게임 유형별 필요 참가자 수를 정의한다 (민겸이 제외)
2. 이미 게임에 참여한 사람들을 Set을 통해 추적한다
3. 현재 모인 인원이 필요 인원에 도달하면 게임을 진행하고 카운트를 증가시킨다
class GameManager {
private var array = [String]()
private var hadGame = Set<String>()
private var gameCount = 0
private let capacity: Int
enum Game: String {
case Y
case F
case O
var capacity: Int {
switch self {
case .Y:
return 2
case .F:
return 3
case .O:
return 4
}
}
}
init(game: String) {
let game = Game(rawValue: game)!
self.capacity = game.capacity - 1 // 민겸이를 제외한 필요 인원
}
func append(_ name: String) {
guard !hadGame.contains(name) && !array.contains(name) else { return }
array.append(name)
if array.count >= capacity {
gameCount += 1
array.forEach { value in
hadGame.insert(value)
}
clear()
}
}
private func clear() {
array.removeAll()
}
func getTotalGameCount() -> Int {
return gameCount
}
}
위의 코드는 정확하게 작동하지만, 더 간결하게 개선할 수 있는 여지가 있다. 아래는 두 가지 최적화 방향이다:
array
와 hadGame
두 개의 컬렉션을 관리하는 것은 불필요한 복잡성을 만들 수 있다. 단일 Set만 사용하여 구현하면 코드가 더 간결해진다:
class GameManager {
private var participants = Set<String>()
private let playerPerGame: Int
init(gameType: String) {
self.playerPerGame = ["Y": 1, "F": 2, "O": 3][gameType] ?? 1
}
func addPlayer(_ name: String) -> Bool {
return participants.insert(name).inserted
}
func getPossibleGameCount() -> Int {
return participants.count / playerPerGame
}
}
이 구현에서는:
클래스를 완전히 제거하고 함수형 접근 방식으로 구현하면 더욱 간결해진다:
func countPossibleGames(players: [String], gameType: String) -> Int {
let requiredPlayers = ["Y": 1, "F": 2, "O": 3][gameType] ?? 1
let uniquePlayers = Set(players).count
return uniquePlayers / requiredPlayers
}
이 방식은:
위의 두 가지 접근법 모두 기존 구현보다 간결하면서도 동일한 결과를 제공한다. 특히 함수형 접근법은 문제의 본질(중복되지 않는 플레이어들로 가능한 최대 게임 수 계산)에 집중하여 불필요한 복잡성을 제거했다.
처음에는 민겸이가 항상 참여한다는 점을 고려하지 않아 문제를 틀렸지만, 수정 후 정답을 맞출 수 있었다. 이 문제를 통해 문제를 꼼꼼히 읽고 조건을 정확히 파악하는 것의 중요성을 다시 한번 느꼈다.
또한 코드를 점진적으로 개선하면서, 동일한 문제를 더 간결하고 효율적으로 해결할 수 있는 여러 방법이 있음을 배웠다.
시간 복잡도: O(N), 여기서 N은 입력받은 사람의 수
공간 복잡도: O(N), Set에 저장되는 사람의 수