프로그래머스 Lv.2 롤케이크 자르기 (Java)

eora21·2022년 11월 3일
1

프로그래머스

목록 보기
38/38

문제 링크

문제 간단 해석

토핑을 기준으로 케이크를 자르는데, 형과 동생이 같은 종류의 토핑을 먹을 수 있는 경우의 수를 구한다.

Java

알고리즘 문제를 풀다기보다, 메서드를 쪼개고 구현하는 데 집중했다.

풀이 코드

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 빼줬다.

여담

메서드를 나누니 해당 흐름에 대해 내 자신도 쉽게 이해할 수 있었고, 어떤 부분이 작성이 덜 됐는지를 체감할 수 있었다. 또한 잘못 풀었을 때 코드를 변경하는 시간도 많이 줄어드는 듯 하다.

그러나 메서드를 나누며 코드를 작성하는 시간이 배로 늘었고, 실제 알고리즘 테스트에서는 시간도 자원이기에 어떤 방식이 더 좋을지 고민해봐야겠다.

profile
나누며 타오르는 프로그래머, 타프입니다.

0개의 댓글