알고리즘문제

[프로그래머스]조이스틱 C++ 문제풀이, 그리디 알고리즘(Greedy)

Kim_Jack 2021. 2. 4. 23:11
반응형

코딩테스트 연습 - 조이스틱

 

코딩테스트 연습 - 조이스틱

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다. ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA 조이스틱을 각 방향으로 움직이면 아래와 같습니다. ▲ - 다

programmers.co.kr

이 문제에서 제일 어려웠던 부분은 문제를 이해하는 것이었다.

 

처음에는 전부 'A' 로 세팅되어있는 문자열을 가지고 있다.

 

그리고 이 문자열을 인자로 들어오는 문자열로 바꿔야하는데 그 최소 횟수를 구하는 것.

 

a -> b -> c -> d .... z  반대로 a -> z  -> y -> x  이런식으로도 갈 수 있다.

 

그리고 문자는 대문자만 사용한다는 조건이 있으니 대놓고 아스키 코드를 이용하라는 문제이다.

 

아스키 코드 범위는 65~90  ,

 

문자 변환 횟수가 ( 90 - 65 ) / 2   보다 값이 높다면 반대로 가는게 더 횟수가 적다는 뜻이다. 

 

마찬가지로 커서위치도  <- , -> 움직일 수 있다.

 

이렇게 조건이 있고 이 조건들을 가지고 가장 최소 횟수를 계산하면 되는데, 말 그대로 그리디하게 접근하면 풀리는 문제이다.

 

1. 커서 기준에서 바꿔야하는 가장 가까운 문자 위치로 이동 

2. 바꿔야할 알파벳으로 바꾸는 최소 횟수 찾기 

3. 커서 위치 갱신 

반복 

 

int solution(string name)
{
    int answer = 0;
    
    char*str = new char[name.length()+1];
    memset(str, 'A', sizeof(char)*name.length());
    str[name.length()] = '\0';
    int cur=0;
    int idx=0;
    
    while(strcmp(str, name.c_str())!= 0)
    {
        int minDis = 20; // name의 최대 길이가 20으로 제한
        for(int i=0; i<name.length(); i++)
        {
            if(name[i]==str[i])
                continue;
            
            int dis = min(abs(cur - i), abs(((int)(name.length()-1)- i+ cur + 1)));
            if(dis < minDis)
            {
                idx=i;
                minDis = dis;
            }
        }
        cur=idx;
        answer += minDis;

        int targetCode = name[cur];
        int curCode = str[cur];
       
        int minCnt = min(abs(targetCode-curCode), abs(90-targetCode+1));
        
        answer += minCnt;
        str[cur]=name[cur];
   
    }
    
    delete [] str;
    return answer;
}

 

 

문자열을 전부 순회해서 바꿔야할 문자열을 찾고 그 문자열 중에 → 방향 ← 방향을 계산해서 가장 짧은 이동 횟수를 가진 문자열 위치로 이동한다

int dis = min(abs(cur - i), abs(((int)(name.length()-1)- i+ cur + 1)));

문자열의 아스키 값을 비교한다 아스키 범위는 65~90 , 거꾸로도 조이스틱을 움직일 수 있으니 마찬가지로 반대 방향으로도 계산해준다.

int minCnt = min(abs(targetCode-curCode), abs(90-targetCode+1));

 

반응형