PS❯Programmers2021-11-153 min read
[프로그래머스] 메뉴 리뉴얼 - Java (백트래킹 조합 & 해시맵 빈도수 계산)
각 손님의 주문에서 코스 요리 길이별 조합을 생성하여 빈도수를 카운트하고 최소 2명 이상 주문한 최빈 메뉴 구성을 선별하는 카카오 기출 풀이
#Programmers#조합#해시#백트래킹#카카오#Java
1. 문제 개요 및 조건 분석
| 항목 | 내용 |
|---|---|
| 문제 이름 | 메뉴 리뉴얼 (Level 2) |
| 플랫폼 / 난이도 | 프로그래머스 (Level 2) / 2021 KAKAO BLIND RECRUITMENT |
| 문제 링크 | 프로그래머스 메뉴 리뉴얼 (Level 2) |
| 입력 조건 | 손님 수 $N \le 20$, 각 주문 단품 수 $\le 10$, 원하는 코스 요리 메뉴 수 course |
| 핵심 규칙 | 각 코스 길이별로 최소 2명 이상의 손님에게 주문된 조합 중 가장 많이 주문된 조합만 선별 (동률 시 모두 포함), 사전순 정렬 출력 |
2. 접근 아이디어: 조합 & 해시 빈도수 카운트
단계별 해결 알고리즘
- 단품 메뉴 사전순 정렬:
- 손님이 "AB"를 시키든 "BA"를 시키든 같은 코스로 취급해야 하므로, 각 주문 문자열을 먼저 알파벳 순으로 정렬합니다 (
Arrays.sort(charArr)).
- 손님이 "AB"를 시키든 "BA"를 시키든 같은 코스로 취급해야 하므로, 각 주문 문자열을 먼저 알파벳 순으로 정렬합니다 (
- 원하는 길이별 조합 생성:
- 각 주문에서
course에 명시된 길이 $k$인 모든 조합을 백트래킹(comb)으로 추출합니다. - 추출된 조합 문자열을 해시맵(
Map<String, Integer>)에 넣어 등장 횟수를 누적합니다.
- 각 주문에서
- 최다 빈도 코스 선별:
- 각 코스 길이 $k$마다 최대 주문 횟수를 구합니다.
- 최대 횟수가 2 이상인 경우, 해당 횟수와 일치하는 모든 조합을 결과 리스트에 추가합니다.
- 결과 정렬:
- 선별된 모든 추천 코스 요리들을 사전순으로 정렬하여 반환합니다.
3. Java 풀이 코드
import java.io.*;
import java.util.*;
class Solution {
private static Map<String, Integer> map = new HashMap<>();
public String[] solution(String[] orders, int[] course) {
List<String> answerList = new ArrayList<>();
for (int c : course) {
map.clear();
int maxCount = 0;
// 각 손님의 주문에 대해 길이 c인 조합 추출
for (String order : orders) {
char[] chars = order.toCharArray();
Arrays.sort(chars); // 문자열 사전순 정렬
generateCombinations(chars, new StringBuilder(), 0, 0, c);
}
// 최다 주문 횟수 탐색
for (int count : map.values()) {
maxCount = Math.max(maxCount, count);
}
// 최소 2명 이상 주문되고 최다 주문된 조합 선별
if (maxCount >= 2) {
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == maxCount) {
answerList.add(entry.getKey());
}
}
}
}
Collections.sort(answerList);
return answerList.toArray(new String[0]);
}
private void generateCombinations(char[] chars, StringBuilder sb, int start, int depth, int targetLen) {
if (depth == targetLen) {
String comb = sb.toString();
map.put(comb, map.getOrDefault(comb, 0) + 1);
return;
}
for (int i = start; i < chars.length; i++) {
sb.append(chars[i]);
generateCombinations(chars, sb, i + 1, depth + 1, targetLen);
sb.deleteCharAt(sb.length() - 1);
}
}
}
4. 복잡도 분석
- 시간 복잡도: $O\left(\sum_{k} \left( N \times \binom{L}{k} \right)\right)$ — 손님 수 $N \le 20$, $L \le 10$이므로 조합 최대 수는 $\binom{10}{5} = 252$개. 손님 20명 전체를 합쳐도 수천 번 연산 이내로 0.05초 미만에 완료.
- 공간 복잡도: $O(K)$ — 각 코스 길이별 조합 문자열을 담는 해시맵.
5. 채점 결과 및 통과 인증

← PREVIOUS LOG
[프로그래머스] 다단계 칫솔 판매 - Java (트리 구조 부모 전파 & 10% 분배)
NEXT LOG →[프로그래머스] 순위 검색 - Java (조합 생성 & 이분 탐색 Binary Search)
COMMENTS // GITHUB DISCUSSIONS (GISCUS)