Q 2037 문자메시지

💡 문제 요약 및 분석

문제를 이해하는 것 부터가 쉽지 않았다..

  • 버튼을 한 번 누를 때 p초가 걸린다. (공백도 마찬가지임)
  • 같은 숫자인 문자를 연속으로 누를 때 w초가 걸린다. 이 경우 버튼을 누르는 시간 p초가 더해진다. (p + w)

💡 알고리즘 설계

  1. 입력

    • StringTokenizer
    • int p, int w
    • String msg
  2. 연산 (예상 시간 복잡도 : O(msg))

    • msg 를 for 문으로 돌면서 char 하나씩 분리한다.
    • if 문으로 버튼 맨 앞 문자(A,D,G,J,M,P,T,W) 및 공백인 경우 p 초를 누적합한다.
    • 그 외의 경우는 p + w 초를 누적합한다.
  3. 출력

    • 누적합을 한 번만 출력한다.

💡 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String time = br.readLine();
        String msg = br.readLine();
        StringTokenizer timeTokens = new StringTokenizer(time);
        int p = Integer.parseInt(timeTokens.nextToken());
        int w = Integer.parseInt(timeTokens.nextToken());
        br.close();

        int sum = 0;
        for (int i = 0; i < msg.length(); i++) {
            char button = msg.charAt(i);
            if (button == 65 || button == 68 || button == 71 || button == 74 || button == 77
                    || button == 80 || button == 84 || button == 87 || button == 32) {
                sum += p;
            } else {
                sum += p + w;
            }
        }
        System.out.println(sum);
    }
}

💡 틀린 부분 분석

  • 문제에서 공백을 연속으로 누를 때는 기다릴 필요가 없다는 부분을 놓쳤다. StringTokenizer 는 연속된 공백은 하나의 구분자로 처리하므로 토큰이 몇 개인지 세고 공백을 계산하는 방식으로 바꿨다.

  • 그럼에도 틀렸다. 다른 사람의 답지를 보니 내가 문제 이해를 잘못했다는 것을 깨달았다. 숫자를 연속해서 입력하는 경우, w초의 대기시간 + 버튼을 누른 횟수 * p 를 해줘야 한다. 나는 이 부분에서 무조건 p + w 로 처리했기 때문에 실패한 것이다. 추가로, A(공백)C 를 입력한다고 가정했을 때는 C 는 대기시간이 필요 없다고 한다. 대기 시간이 들어가는 경우는 AC 처럼 같은 버튼을 연속해서 눌러야 할 때 구분점을 두기 위해 있는 룰인 것 같다.

  • 고쳤는데도 틀려서 다시 확인했는데, 공백을 연속해서 누를 때 기다리지 않아도 된다고 해서 공백이 여러 번 들어가면 P초 한 번만 누르고 마는 건줄 알았는데 아니었다. 버튼을 누르긴 눌렀으니 누른만큼 누적합해야한다…

💡 알고리즘 재설계 및 정답 코드

  1. 입력

    • StringTokenizer
    • int p, int w
    • String msg
    • 이차원 배열
  2. 연산

    • 입력된 문자열을 공백으로 나눈다. (공백 입력시간 계산)
    • prevGroup 변수로 연속된 그룹의 문자일 경우 대기시간 w 초를 더한다.
    • 이차원 배열에서 i = 그룹, j = 버튼을 누르는 횟수 가 된다.
  3. 출력

    • 누적합을 한 번만 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    static char[][] dial = {
            {'A','B','C'}, {'D','E','F'}, {'G','H','I'},
            {'J','K','L'}, {'M','N','O'}, {'P','Q','R','S'},
            {'T','U','V'}, {'W','X','Y','Z'}
    };

    static int prevGroup = -1;

    public static int cal(char c, int p, int w) {
        int sum = 0;
        for (int i = 0; i < dial.length; i++) {
            for (int j = 0; j < dial[i].length; j++) {
                if (dial[i][j] == c) {
                    if (prevGroup == i) sum += w;
                    sum += (j + 1) * p;
                    prevGroup = i;
                    return sum;
                }
            }
        }
        return 0;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        String time = br.readLine();
        String msg = br.readLine();
        StringTokenizer timeTokens = new StringTokenizer(time);
        int p = Integer.parseInt(timeTokens.nextToken());
        int w = Integer.parseInt(timeTokens.nextToken());
        br.close();

        int sum = 0;
        for (int i = 0; i < msg.length(); i++) {
            char c = msg.charAt(i);
            if (c == ' ') {
                sum += p;
                prevGroup = -1;
                continue;
            }
            sum += cal(c, p, w);
        }
        System.out.println(sum);
    }

}

💡 시간 복잡도, 공간 복잡도

시간 복잡도공간 복잡도
O(n)O(n)
  • ⏱️ main 에서 for 반복문은 들어오는 문자열 개수 n 만큼 시간을 소비하고, cal 함수는 char 배열을 순회하는데, 이 때 char 배열은 정해진 값이므로 O(1) 만큼 시간을 소비한다. 따라서 O(n) 이다.

  • 🧠 입력 문자열과 배열, 기타 변수 등이 있는데, 문자열은 n 만큼 공간을 차지할 것이고, 나머지는 상수이므로 O(1) 차지한다.

💡 느낀점 및 기억할 정보

코딩보다 문제를 이해하는게 더 힘들었다 ㅜㅜ 계속 잘못된 이해를 바탕으로 코드를 짰으니 통과할 수 있을 리 없었다. 문제를 정확히 이해하고 넘어갈 것 !! 기본 중의 기본이다.