토핑을 기준으로 케이크를 자르는데, 형과 동생이 같은 종류의 토핑을 먹을 수 있는 경우의 수를 구한다.
알고리즘 문제를 풀다기보다, 메서드를 쪼개고 구현하는 데 집중했다.
import java.util.*;
class Solution {
public int solution(int[] topping) {
Cake cake = new Cake();
return cake.split(topping);
}
}
class Cake {
private Map<Integer, Integer> myTopping = new HashMap<>();
private Set<Integer> brothersTopping = new HashSet<>();
private void putToppingCnt(int[] toppings) {
for (int topping : toppings) {
int cnt = myTopping.getOrDefault(topping, 0);
myTopping.put(topping, cnt + 1);
}
}
public int split(int[] toppings) {
putToppingCnt(toppings);
return toppingEqualCnt(toppings);
}
private int toppingEqualCnt(int[] toppings) {
int equalCnt = 0;
for (int topping : toppings) {
moveTopping(topping);
if (myTopping.size() < brothersTopping.size()) {
break;
}
if (myTopping.size() == brothersTopping.size()) {
equalCnt++;
}
}
return equalCnt;
}
private void moveTopping(int topping) {
brothersTopping.add(topping);
int toppingCnt = myTopping.get(topping);
if (toppingCnt == 1) {
myTopping.remove(topping);
return;
}
myTopping.put(topping, toppingCnt - 1);
}
}
public int solution(int[] topping) {
Cake cake = new Cake();
return cake.split(topping);
}
명시적으로 Cake를 나눈다(split)를 알 수 있게끔 작성했다.
public int split(int[] toppings) {
putToppingCnt(toppings);
return toppingEqualCnt(toppings);
}
myTopping에 현재 토핑 값들을 정리하고, 토핑의 종류가 같아지는 경우의 수를 받아오기로 했다.
putToppingCnt
라는 이름이 명확하지 않아서 아쉽다. Map 이름을 코드 작성 중간에 바꾸었는데, 메서드명을 신경쓰지 못 했다. putMyTopping
또는 putTopping
으로 변경한다면 좋을 것 같다.
private void putToppingCnt(int[] toppings) {
for (int topping : toppings) {
int cnt = myTopping.getOrDefault(topping, 0);
myTopping.put(topping, cnt + 1);
}
}
토핑 종류를 key로 하여 현재 토핑 갯수값을 가져오는데, key가 있다면 해당 값을, 없다면 0을 받아왔다.
해당 토핑 갯수값을 1 증가하여 넣어줬다.
private int toppingEqualCnt(int[] toppings) {
int equalCnt = 0;
for (int topping : toppings) {
moveTopping(topping);
if (myTopping.size() < brothersTopping.size()) {
break;
}
if (myTopping.size() == brothersTopping.size()) {
equalCnt++;
}
}
return equalCnt;
}
토핑을 하나씩 동생에게 옮겨주며, 토핑 종류의 갯수가 같은지 확인한다.
만약 동생의 토핑 종류가 더 많다면, 더 이상 옮겨줘봤자 의미가 없으니 중지.
토핑 종류가 같다면 cnt를 1 증가시켰다.
private void moveTopping(int topping) {
brothersTopping.add(topping);
int toppingCnt = myTopping.get(topping);
if (toppingCnt == 1) {
myTopping.remove(topping);
return;
}
myTopping.put(topping, toppingCnt - 1);
}
토핑을 동생에게 옮기되, 만약 내 케이크 위에 해당 토핑이 1개밖에 남지 않았을 때는 해당 종류의 토핑이 아예 남지 않으므로 remove로 제거.
아니라면 해당 토핑의 갯수를 1 빼줬다.
메서드를 나누니 해당 흐름에 대해 내 자신도 쉽게 이해할 수 있었고, 어떤 부분이 작성이 덜 됐는지를 체감할 수 있었다. 또한 잘못 풀었을 때 코드를 변경하는 시간도 많이 줄어드는 듯 하다.
그러나 메서드를 나누며 코드를 작성하는 시간이 배로 늘었고, 실제 알고리즘 테스트에서는 시간도 자원이기에 어떤 방식이 더 좋을지 고민해봐야겠다.