본문 바로가기

코딩/프로그래머스

[프로그래머스/JAVA] 고득점Kit > 탐욕법(Greedy) > 조이스틱 (by 다알쥐AI)

728x90

고득점Kit > 탐욕법(Greedy) > 조이스틱

 

 

※ 주의 : 문제풀이 방법은 다양합니다. 참고만 해주세요

[문제설명]

더보기

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

 

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

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

 

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

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

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

 

제한 사항

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

입출력 예

 


[간단설명]

조이스틱을 위, 아래, 왼쪽, 오른쪽으로 움직여서 문자열을 만들 때, 조작횟수 최소값 찾기

 

[접근방법]

1. 알파벳을 위, 아래 움직이는 횟수를 누적 기록한다

2. 알파벳을 왼쪽, 오른쪽 움직이는 횟수의 최소값을 구한다.

    1) 인덱스 0번째 부터 시작해서, 오른쪽으로 움직였을때

    2) 인덱스 0번째 부터 시작해서, 왼쪽으로 움직였을때

    3) min(오른쪽, 왼쪽)

3. 위, 아래 횟수, 왼쪽, 오른쪽 횟수를 더해서 정답 리턴

 

[주의사항]

완전탐색으로 접근할 경우, 경우의 수가 너무 많다.

Greedy 알고리즘 방식이 가장 이해하기 쉽다.

 

[소스공개]

class Solution {
    public int solution(String name) {
        int length = name.length(); //문자열 길이
        int upDown = 0;             //위아래 카운트
        int leftRight = length-1;   //왼쪽오른쪽 카운트
        
        // 문자열 길이만큼 반복
        for(int i=0; i<length; i++){
            // 각 알파벳별로 움직인 횟수를 누적해서 기록
            // ex) BBBAAB 
            // upDown = 1+1+1+0+0+1 = 4 (정답)
            upDown += Math.min(name.charAt(i)-'A', 'Z'-name.charAt(i)+1);
            
            // 다음 알파벳이 A일 때, 연속되는 A의 인덱스를 구한다
            int next = i+1;
            while(next<length && name.charAt(next)=='A'){
                next++;
            }
            // 시작 인덱스 0번째 -> 오른쪽으로 커서를 움직였을 때, 왼쪽으로 커서를 움직였을 때 최소값 구하기
            // ex) BBBAAB
            // ---------------------------------------
            // [1단계]
            // i = 0
            // next = 1
            // next = 1
            // leftRight = 5
            // right => i+length-next+i => 0+6-1+0 => 5
            // left => i+length-next+length-next => 0+6-1+6-1 => 10
            // leftRigth = 5
            // ---------------------------------------
            // [2단계]
            // i = 1
            // next = 2
            // next = 2
            // leftRight = 5
            // right => i+length-next+i => 1+6-2+1 => 6
            // left => i+length-next+length-next => 1+6-2+6-2 => 9
            // leftRigth = 5
            // ---------------------------------------
            // [3단계] 
            // i = 2
            // next = 3
            // next = 5
            // leftRight = 5
            // right => i+length-next+i => 2+6-5+2 => 5
            // left => i+length-next+length-next => 2+6-5+6-5 => 4
            // leftRigth = 4 (정답)
            leftRight = Math.min(leftRight, Math.min((i+length-next+i),(i+length-next+length-next)));
            
        }
        // ex) BBBAAB
        // upDown + leftRight = 4+4 = 8(정답)
        return upDown+leftRight;
    }
}

 

[실행결과]

728x90