코딩 테스트 - 조이스틱

김혁·2025년 7월 25일

프로그래머스

목록 보기
18/65

조이스틱

문제 링크 : 조이스틱

문제 설명

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다.
ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA

조이스틱을 각 방향으로 움직이면 아래와 같습니다.

▲ - 다음 알파벳
▼ - 이전 알파벳 (A에서 아래쪽으로 이동하면 Z로)
◀ - 커서를 왼쪽으로 이동 (첫 번째 위치에서 왼쪽으로 이동하면 마지막 문자에 커서)
▶ - 커서를 오른쪽으로 이동 (마지막 위치에서 오른쪽으로 이동하면 첫 번째 문자에 커서)

예를 들어 아래의 방법으로 "JAZ"를 만들 수 있습니다.

- 첫 번째 위치에서 조이스틱을 위로 9번 조작하여 J를 완성합니다.
- 조이스틱을 왼쪽으로 1번 조작하여 커서를 마지막 문자 위치로 이동시킵니다.
- 마지막 위치에서 조이스틱을 아래로 1번 조작하여 Z를 완성합니다.
따라서 11번 이동시켜 "JAZ"를 만들 수 있고, 이때가 최소 이동입니다.

만들고자 하는 이름 name이 매개변수로 주어질 때, 이름에 대해 조이스틱 조작 횟수의 최솟값을 return 하도록 solution 함수를 만드세요.

제한 사항

  • name은 알파벳 대문자로만 이루어져 있습니다.
  • name의 길이는 1 이상 20 이하입니다.

입출력 예

namereturn
"JEROEN"56
"JAN"23

풀이 방법

  • 해당 문제는 상당히 어려웠다...
  • 조이스틱을 위아래로 움직여서 알파벳을 변경하는 것은 위, 아래 중에서 횟수가 덜 필요로 하는 방향으로 움직이게끔 하면 된다.
  • 커서를 좌우로 움직이는 것이 이 문제의 핵심으로 처음에는 dfs 완전 탐색을 통해서 풀어야 하나 했지만, 각 인덱스에서 최소값을 그리디하게 풀 수 있을 것 같아서 그리디한 방법을 통해 문제를 해결하고자 했다.
  • 기본적인 값으로는 오른쪽으로 쭉 움직이는 name의 길이 - 1 값을 지정하고, 만약에 A가 연속되어 나온다면 해당 부분까지 오른쪽으로 갔다가 왼쪽으로 돌아가는 방법, 처음에 왼쪽으로 갔다가 오른쪽으로 해당 부분까지 돌아오는 방법 2가지를 비교해서 가장 작은 값을 가지는 값을 최소 값으로 지정했다.
    • 시간복잡도는 O(N)으로 n의 최대값은 20이기 때문에 상당히 좋은 문제 풀이 방법으로 보인다. 완전 탐색을 통해도 풀 수 있게 n의 최대값을 20으로 잡지 않았나 싶다.

구현

#include <string>
#include <vector>

using namespace std;

int solution(string name) {
    int answer = 0;
    int n = name.size();
    int minMove = n - 1;
    
    for(int i = 0; i < n; i++){
        // 알파벳 변환하기
        answer += min(name[i] - 'A', 'Z' + 1 - name[i]);
        
        // 커서 조작 최소화값 찾기
        int next = i + 1;
        while(next < n && name[next] == 'A'){
            next++;
        }
        if (next > i + 1){
            // 오른쪽으로 갔다가 왼쪽으로 가는 경우
            int rightLeft = i * 2 + n - next;
            minMove = min(minMove, rightLeft);
            // 왼쪽으로 갔다가 오른쪽으로 가는 경우
            int leftRight = (n - next) * 2 + i;
            minMove = min(minMove, leftRight);
        }
    }
    answer += minMove;
    
    return answer;
}
profile
게임 개발자를 향해..

0개의 댓글