프로그래머스 | LV.2 조이스틱 - 구현 문풀 (Java)

728x90

⬛ 프로그래머스 | LV.2 조이스틱 - 구현 문풀 (Java)

https://school.programmers.co.kr/learn/courses/30/lessons/42860#

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제 설명


💚문제 접근 방식

어려웠다. 이 문제는 커서를 제대로 움직이는 게 핵심이다. 최소 조작 횟수를 만드는 핵심은 (1) ['A' ~ 글자] vs [글자 ~ 'Z] 사이의 거리를 비교하여 각 글자에 대한 최소 조작을 하는 것이고, (2) 최소 조작을 위해 처리할 글자에 대한 커서 조작을 최소로 하는 것이 중요하다. 

 

처음에는 ‘커서’ 조작에 대한 내용을 잘못 이해해서 정말 오래 헤맸다. 위,아래 이동과 커서 왼쪽,오른쪽 이동이 뭔 차이가 있는지 모르겠어서 오랫동안 헤맸는데, 처음부터 A로 구성된 문자열에 대해서는 더 이상 처리할 조작이 없기 때문에, 조작을 위한 별다른 처리를 해줄 필요가 없다. 이 경우 다음 A로 진입해서 처리를 하느니, 뒤로 가서 다른 문자에 커서를 올리고 행동을 하는 게 더 최소 조작을 한다 이 소리였다 …

 

커서는 기본적으로 name길이 -1 만큼 움직일거다. 이게 기본값이고, 이거보다 더 줄여서 커서 이동 횟수를 줄일 수 있다면 min으로 다시 세팅하는 게 포인트이다. 아래 코드의 경우 연속된 A에 대해서는 처리해줄 필요도, 커서를 움직일 필요도 없으므로 연속된 A의 마지막 위치 idx를 지칭한 뒤, 기존 move와 I*2 + (move-idx) 와 비교하는 부분 중 작은 값으로 세팅해야 된다.

 

그리고 2022년 이후 테스트 케이스에서는 BBBBAAAAAAB 처럼 처음부터 뒷부분을 먼저 입력하는 게 빠른 경우까지 고려해야 정답 처리가 된다고 한다 ㅠㅠ 어렵군 

            // 순서대로 가는 것과, 뒤로 돌아가는 것 중 이동수가 적은 것을 선택
            move = Math.min(move, i * 2 + length - index);
            // 2022년 이전 테스트 케이스만 확인하면 여기까지해도 정답처리가 되기 때문에, 이전 정답들에는 여기까지만 정리되어 있지만,
            // BBBBAAAAAAAB 와 같이, 처음부터 뒷부분을 먼저 입력하는 것이 더 빠른 경우까지 고려하려면 아래의 코드가 필요합니다.
            move = Math.min(move, (length - index) * 2 + i);

💚 제출 코드

import java.util.*;
class Solution {
    public int solution(String name) {
        int answer = 0;
        int length = name.length();

        int index; // 다음 값들을 확인할 때 사용
        int move = length - 1; // 좌우 움직임 수를 체크

        for(int i = 0; i < name.length(); i++){
            answer += Math.min(name.charAt(i) - 'A', 'Z' - name.charAt(i) + 1);

            index = i + 1;
            // 연속되는 A 갯수 확인
            while(index < length && name.charAt(index) == 'A'){
                index++;
            }

            // 순서대로 가는 것과, 뒤로 돌아가는 것 중 이동수가 적은 것을 선택
            move = Math.min(move, i * 2 + length - index);
            // 2022년 이전 테스트 케이스만 확인하면 여기까지해도 정답처리가 되기 때문에, 이전 정답들에는 여기까지만 정리되어 있지만,
            // BBBBAAAAAAAB 와 같이, 처음부터 뒷부분을 먼저 입력하는 것이 더 빠른 경우까지 고려하려면 아래의 코드가 필요합니다.
            move = Math.min(move, (length - index) * 2 + i);
        }
        return answer + move;
    }
}
728x90