[JAVA / Algorithm] 프로그래머스 연습문제 - 둘만의 암호

waterlyn·2023년 6월 3일
0
post-thumbnail
post-custom-banner

썸네일 이미지 출처 - 토심이 작가님 인스타그램


문제 바로가기

문제

해결

문자열이 두개가 주어지는데, 하나는 변환 대상 문자열(s), 하나는 문자열 연산에서 제외해야 하는 문자를 나열한 것(skip)입니다.
변환 대상 문자열의 각 문자를 주어진 index만큼 뒤의 알파벳으로 바꾼 결과를 반환해야 하는 규칙인데, 이때 skip에 들은 알파벳은 넘기고, 뒤로 이동해야 합니다.

예를 들어, 예시처럼 b가 skip에 들어있으므로, a부터 index만큼 뒤로 미룰때 한번 미루면 b가 되어야 하는데, b가 skip에 들어있으므로 뒤로 간 횟수에서 제외해야 하는 것입니다.

이러한 규칙을 만족하면서 변환된 문자열을 반환하는 것이 이 문제의 해답입니다.

저는 처음에 코드를 다음과 같이 작성했습니다.

import java.util.*;

class Solution {
    
    char z = 'z';
    
    public String solution(String s, String skip, int index) {
        StringBuilder sb = new StringBuilder();
        
        List<Character> alphabets = new ArrayList<>(Arrays.asList('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'));
        
        for(int i = 0; i < skip.length(); i++){
            alphabets.remove(Character.valueOf(skip.charAt(i)));
        }
        
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            int idx = alphabets.indexOf(c);
            if(idx + index >= alphabets.size()){
                sb.append(alphabets.get(idx + index - alphabets.size()));
            } else {
                sb.append(alphabets.get(idx + index));
            }
        }
        
        return sb.toString();
    }
}

부분적으로 설명해보겠습니다!

List<Character> alphabets = new ArrayList<>(Arrays.asList('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'));
        
for(int i = 0; i < skip.length(); i++){
    alphabets.remove(Character.valueOf(skip.charAt(i)));
}

알파벳들에서 제외하여야 하는 것들을 제외하고 사용하는 알파벳만 가지는 리스트를 만들어주었습니다.

for(int i = 0; i < s.length(); i++){
   	char c = s.charAt(i);
    int idx = alphabets.indexOf(c);

위의 코드는 주어진 문자열의 하나를 가져와 변환해주기 위해 반복문을 시작합니다.
그리고 제가 구한 활용하는 알파벳 리스트에서 해당 알파벳의 인덱스를 가져옵니다.

if(idx + index >= alphabets.size()){
     sb.append(alphabets.get(idx + index - alphabets.size()));
} else {
     sb.append(alphabets.get(idx + index));
}

그리고 인덱스에 주어진 값만큼 더한 것이 알파벳 리스트를 벗어나는 경우 z보다 값이 커지는 것이므로 인덱스 값을 조정해주기 위해 가진 리스트 길이만큼 빼줍니다.
그리고 빼준 후 구한 인덱스에 해당하는 알파벳을 StringBuilder에 append 해줍니다.
(만약 더한 인덱스 값이 리스트를 벗어나지 않는다면 그대로 가져가면 됩니다!)

⚒️ 제가 여기서 틀렸어요!!
제가 여기서 놓친것이 있습니다....
바로 리스트의 길이만큼 빼주어도 더한 인덱스 값이 리스트 길이보다 클 수 있다는 것입니다. 그래서 해당 코드를 제출했을때 몇몇 테스트 케이스에서 런타임 오류가 발생하는 것을 확인했습니다 🥺

그래서 저는 바로 위의 코드를 다음과 같이 변경해주었습니다.

if(idx + index >= alphabets.size()){
   	sb.append(alphabets.get(((idx + index) - alphabets.size()) % alphabets.size()));
} else {
   	sb.append(alphabets.get(idx + index));
}

바로 인덱스를 계산해줄 때 리스트의 길이만큼 빼준 것에서 리스트의 길이만큼 나눈 나머지를 인덱스로 활용하였습니다.
그러면 계산된 인덱스가 리스트를 벗어나도 나머지로 구하기 때문에 런타임 에러가 더 이상 발생하지 않습니다!

최종 코드

import java.util.*;

class Solution {
    
    char z = 'z';
    
    public String solution(String s, String skip, int index) {
        StringBuilder sb = new StringBuilder();
        
        List<Character> alphabets = new ArrayList<>(Arrays.asList('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'));
        
        for(int i = 0; i < skip.length(); i++){
            alphabets.remove(Character.valueOf(skip.charAt(i)));
        }
        
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            int idx = alphabets.indexOf(c);
            if(idx + index >= alphabets.size()){
                sb.append(alphabets.get(((idx + index) - alphabets.size()) % alphabets.size()));
            } else {
                sb.append(alphabets.get(idx + index));
            }
        }
        
        return sb.toString();
    }
}


성공했습니다 !! ✨

profile
Hello there 🖤
post-custom-banner

0개의 댓글