Question
문제 해설
- 손님들은 단품메뉴를 주문
스카피
는 단품메뉴를 조합해서 코스요리를 만드려고 함
- 코스요리에 들어갈 단품 메뉴 기준
- 각 손님들이 한번 주문할 때 가장 많이 함께 주문한 단품메뉴들
- 코스요리 메뉴는 최소 2가지 이상의 단품메뉴
- 최소 2명 이상의 손님으로부터 주문된 단품메뉴 조합
- 새로 추가하게 될 코스요리의 메뉴 구성을 구하여라
Solution
풀이 접근 방법
- 단품 메뉴들의 갯수가 담긴 배열 :
course
- course 배열에 들어있는 값 = 코스요리 메뉴구성 문자열의 길이
- "만약 가장 많이 함께 주문된 메뉴 구성이 여러 개라면, 모두 배열에 담아 return"
- "가장 많이" : 길이가 같은 코스요리 메뉴가 있으면 더 많이 나온(빈도수가 높은) 메뉴만 고른다
- "모두 배열에 담아" : 코스요리 메뉴 구성은 다르지만, 길이와 빈도수가 같으면 모두 정답 배열에 담음
- "배열의 각 원소에 저장된 문자열 또한 알파벳
오름차순
으로 정렬"
- 뽑힌 코스요리 메뉴는 모두 오름차순 정렬해서 비교
- 즉, "WX"랑 "XW"는 같은 코스요리 메뉴로 취급한다
- "최소 2명 이상의 손님으로부터 주문된 단품메뉴 조합에 대해서만 코스요리 메뉴 후보에 포함"
- 코스요리 메뉴 조합(빈도수)이 2 이상이여야한다
정답 코드
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
public class Main {
static HashMap<String, Integer> courseComb;
static HashMap<Integer, Integer> lenFrequency;
public static void main(String[] args) {
String[] orders = new String[] { "ABCFG", "AC", "CDE", "ACDE", "BCFG", "ACDEH" };
int[] courses = new int[] { 2, 3, 4 };
System.out.println(Arrays.toString(solution(orders, courses)));
orders = new String[] { "ABCDE", "AB", "CD", "ADE", "XYZ", "XYZ", "ACD" };
courses = new int[] { 2, 3, 5 };
System.out.println(Arrays.toString(solution(orders, courses)));
orders = new String[] { "XYZ", "XWY", "WXA" };
courses = new int[] { 2, 3, 4 };
System.out.println(Arrays.toString(solution(orders, courses)));
}
static String[] solution(String[] orders, int[] course) {
ArrayList<String> answer = new ArrayList<String>();
courseComb = new HashMap<String, Integer>();
lenFrequency = new HashMap<Integer, Integer>();
for (int c : course) {
lenFrequency.put(c, 0);
}
for (String order : orders) {
for (int courseLength : course) {
if (order.length() >= courseLength) {
comb(new boolean[order.length()], 0, courseLength, order);
}
}
}
for (String newCourse : courseComb.keySet()) {
int length = newCourse.length();
if (lenFrequency.get(length) >= 2 && lenFrequency.get(length) == courseComb.get(newCourse)) {
answer.add(newCourse);
}
}
answer.sort(null);
return answer.toArray(new String[answer.size()]);
}
static void comb(boolean[] visited, int start, int pick, String order) {
if (pick == 0) {
StringBuilder newMenu = new StringBuilder();
for (int i = 0; i < visited.length; i++) {
if (visited[i])
newMenu.append(order.charAt(i));
}
String sortedNewMenu = sortedString(newMenu.toString());
courseComb.put(sortedNewMenu, courseComb.getOrDefault(sortedNewMenu, 0) + 1);
int frequency = courseComb.get(sortedNewMenu);
int length = sortedNewMenu.length();
lenFrequency.put(length, Math.max(frequency, lenFrequency.get(length)));
return;
}
for (int i = start; i < order.length(); i++) {
visited[i] = true;
comb(visited, i + 1, pick - 1, order);
visited[i] = false;
}
}
static String sortedString(String s) {
char[] stringChar = s.toCharArray();
Arrays.sort(stringChar);
return new String(stringChar);
}
}
알.쓸.유.메(알아두면 쓸데있는 유용한 메소드)
Map.getOrDefault
java.util.Map
public V getOrDefault(Object key,V defaultValue)
- 찾고자하는 key 값이 map에 있으면 해당 key의 vlaue 반환, 없으면 defaultValue 반환