이번 미션의 핵심 로직은 "비상 근무표를 짜되, 한 사람이 이틀 연속 근무할 수 없다"는 규칙을 지키는 것이었습니다. 만약 연속 근무가 발생하면, 다음 순번의 근무자와 순서를 바꿔야 합니다.
처음에는 직관적으로 생각나는 대로 코드를 짰지만, 곧 복잡한 `for`문과 `while`문의 늪에 빠지고 말았습니다. 어떻게 이 로직을 개선했는지, 그 리팩토링 과정을 공유합니다.
1. 초기 접근: 일단 배정하고, 나중에 고치자
처음에는 단순하게 생각했습니다.
- 순서대로 날짜에 사원을 다 집어넣는다.
- 처음부터 끝까지 훑으면서 "어? 얘 연속이네?" 싶으면 뒤의 사람과 바꾼다.
- 바꾸고 나서 또 겹칠 수 있으니, 문제가 없어질 때까지 `while(true)`로 계속 검사한다.
// 개선 전 코드 (의사 코드)
while (hasConsecutiveWorker(schedule)) {
for (i in 0 until schedule.size - 1) {
if (schedule[i] == schedule[i+1]) {
swap(schedule, i+1, findNextWorker(schedule))
}
}
}
문제점
- 비효율: 이미 배정된 스케줄을 몇 번이나 다시 훑어야 할지 모릅니다.
- 복잡도: while 안에 for 안에 if... 들여쓰기(Depth)가 3단계, 4단계로 깊어집니다.
- 가독성: 코드를 읽는 사람이 흐름을 파악하기 어렵습니다.
2. 사고의 전환: 넣기 전에 검사하자 (Queue 활용)
"이미 어지러진 방을 치우는 것보다, 물건을 놓을 때 제자리에 놓는 게 더 빠르지 않을까?"
이런 생각으로 자료구조 Queue(대기열)를 도입했습니다.
개선된 로직
- 평일 근무자 명단과 휴일 근무자 명단을 각각 Queue (LinkedList)에 넣습니다.
- 하루씩 날짜를 진행하며 근무자를 뽑습니다(poll).
- 검사: "방금 뽑은 사람이 어제 일한 사람인가?"
- Yes: 그 사람을 다시 대기열 맨 앞(addFirst)에 잠깐 넣어두고, 그 다음 사람을 뽑습니다. (순서 교체 효과)
- No: 그대로 근무 시킵니다.
- 근무한 사람은 대기열의 맨 뒤(addLast)로 보내 순번을 돌립니다.
// 개선된 코드 예시
val weekdayQueue = LinkedList(weekdayWorkers)
var previousWorker: Worker? = null
dayList.forEach { day ->
var candidate = weekdayQueue.poll() // 1. 후보 뽑기
if (candidate == previousWorker) { // 2. 연속 근무 체크
val nextWorker = weekdayQueue.poll() // 다음 사람 뽑기
weekdayQueue.addFirst(candidate) // 원래 후보는 다시 넣어두기 (순서 교체)
candidate = nextWorker // 후보 변경
}
day.worker = candidate
previousWorker = candidate
weekdayQueue.addLast(candidate) // 3. 로테이션
}
3. 결과 비교
- Time Complexity: 기존 O(N^2) 이상의 불확실한 로직에서, O(N) (날짜 수만큼만 순회)으로 명확해졌습니다.
- Clean Code: `while` 루프가 사라졌고, 들여쓰기는 1단계로 줄어들어 코드가 훨씬 깔끔해졌습니다.
마무리
알고리즘 문제를 풀 때 "일단 구현"하는 것도 중요하지만, "적절한 자료구조(Queue)를 쓰면 로직 자체가 단순해진다"는 것을 배울 수 있었습니다. 복잡한 조건문으로 덕지덕지 기운 코드가 있다면, 데이터의 흐름 자체를 바꿀 수 있는지 고민해보세요.
'Dev Log > Kotlin' 카테고리의 다른 글
| Interface 와 Abstract Class (0) | 2026.05.25 |
|---|---|
| [코틀린] 복잡한 문자열 검증, 한 줄로 끝내는 정규식(Regex) 정복하기 (0) | 2026.01.31 |
| [우테코 | 안드로이드] 코틀린 최종 코딩테스트 준비, 과제 모음 (1) | 2026.01.06 |
| [우테코/코테] "검색 시간 0초" 시험장용 만능 유틸 코드 모음집 (복붙용) (1) | 2026.01.06 |
| [우테코] 🏪 편의점 과제: 재고가 먼저인가 검증이 먼저인가? Controller와 Service의 역할 분담과 예외 처리 순서 (0) | 2026.01.06 |