메뉴 리뉴얼 72411
https://school.programmers.co.kr/learn/courses/30/lessons/72411 (opens in a new tab)
풀이
애초에 부분 집합을 구하는 로직이 떠오르지 않았던 문제이다. 하나의 템플릿처럼 외워도 괜찮을 것 같다.
class Solution {
// HashMap< 세트의 메뉴 개수, HashMap< 코스, 코스 개수 >
private static HashMap<Integer, HashMap<String, Integer> /* 코스 : 개수 */> courseMap;
public String[] solution(String[] orders, int[] course) {
// 해시맵 초기화
courseMap = new HashMap<>();
for (int i : course) {
courseMap.put(i, new HashMap<>());
}
// ❶ 코스를 배열로 만들고 오름차순 정렬해서 가능한 모든 메뉴 구성을 구함
for (String order : orders) {
char[] orderArray = order.toCharArray();
Arrays.sort(orderArray);
combinations(0, orderArray, "");
}
ArrayList<String> answer = new ArrayList<>();
// ❷ 모든 코스 후보에 대해서
for (HashMap<String, Integer> count : courseMap.values()) {
count.values()
.stream()
.max(Comparator.comparingInt(o -> o)) // ❸ 가장 빈도수가 높은 코스를 찾음
.ifPresent(cnt -> count.entrySet() // ❹ 코스에 대한 메뉴 수가 가능할 때만
.stream()
// ❺ 최소 2명 이상의 손님으로부터 주문된 단품메뉴 조합에 대해서만
.filter(entry -> cnt.equals(entry.getValue()) && cnt > 1)
// ❻ 코스 메뉴만 answer 리스트에 추가
.forEach(entry -> answer.add(entry.getKey())));
}
Collections.sort(answer); // ❼ 오름차순으로 정렬
return answer.toArray(new String[0]);
}
// 만들 수 있는 모든 조합을 재귀 함수를 이용해서 구현
public static void combinations(int idx, char[] order, String result) {
// 필요한 코스 메뉴의 수와 일치하는 것만 저장
if (courseMap.containsKey(result.length())) {
HashMap<String, Integer> map = courseMap.get(result.length());
// 해당 코스의 수를 1증가
map.put(result, map.getOrDefault(result, 0) + 1);
}
for (int i = idx; i < order.length; i++) {
combinations(i + 1, order, result + order[i]);
}
}
}