Algorithm/Java

[프로그래머스/JAVA] 시저암호

dbfl9911 2024. 11. 17. 18:22

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

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

📌 문제 요약 

주어진 문자열 s의 각 알파벳을 n만큼 밀어서 암호화하는 문제로, 대문자와 소문자는 각각 순환되며, 공백은 그대로 유지해야 합니다.



[ 오답 노트 ]
❌ 기존 오답 코드

class Solution {
    public String solution(String s, int n) {
        String answer = "";
        // AB -> BC -> CD -> DE -> EF -> FG
        //    1     1     1
        // a B z -> b C a -> c D b -> d E c -> e F d
        //       1        1        1        1
        
        // 문자에 공백이 있을 때, 없을 때 구분?
        String[] str = s.split(" "); // ["AB"]  ["a", "B", "z"]
        char ch;
        for(int i = 0; i < str.length; i++) {
            if(str[i].length() > 1) {
                for(int j = 0; j < str[i].length(); j++) {
                    // 'A'+ 1 = "B"?
                    ch = (char)(Integer.parseInt(str[i].charAt(j)) + 1);
                    answer += String.valueOf(ch);
                }
            }else{
                answer += str[i] + 1;
            }
            
        }
        
        return answer;
    }
}



📌 기존 코드의 문제점

 

1. split(" ") 사용으로 인한 공백 처리 문제

 

  • 공백으로 문자열을 나누면 공백이 사라져 원래 문자열의 공백 정보를 잃습니다.
  • 예: "a B z" → ["a", "B", "z"]

 

 

2. Integer.parseInt(str[i].charAt(j)) 사용 오류

 

  • char 타입을 int로 변환하려면 ASCII 값을 직접 활용하거나 Character 관련 메서드를 사용해야 합니다.
  • Integer.parseInt는 문자열을 숫자로 변환할 때 사용하는 메서드로 char 변환에는 부적합합니다.

 

 

3. 알파벳 범위 초과 처리 누락

 

  • z에서 1을 더하면 a로 순환해야 하지만, 해당 처리가 없습니다.
  • 대문자(AZ)와 소문자(az)도 각각 독립적으로 순환해야 합니다.

 

 

4. else 블록의 처리 오류

  • answer += str[i] + 1은 문자열과 숫자를 더해 문자열이 아닌 값이 나옵니다.
  • 예: "a" + 1은 "a1"이 아니라 ASCII 값 연산이 됩니다.

 

 



[ 정답 코드 & 올바른 풀이 ]


📌 올바른 풀이

 

1. 공백 처리 유지

공백을 제거하지 않고 원본 문자열의 모든 문자를 순서대로 처리합니다.

 

 

 

2. char와 ASCII 값 활용

  • char를 그대로 사용하며, 알파벳 순환을 위해 ch - 'a' 또는 ch - 'A'를 계산합니다.

 

 

3. 알파벳 순환 처리

 

  • (ch - 'a' + n) % 26 + 'a'로 소문자를 순환 처리합니다.
  • 대문자도 동일한 방식으로 처리하되, 기준값을 'A'로 설정합니다.

 

 

4. 효율적인 반복

split을 사용하지 않고, 문자열을 한 문자씩 처리하여 불필요한 배열 분할 및 추가 반복을 제거했습니다.

 

 



📌 정답 코드

class Solution {
    public String solution(String s, int n) {
        String answer = "";
        // AB -> BC -> CD -> DE -> EF -> FG
        //    1     1     1
        // a B z -> b C a -> c D b -> d E c -> e F d
        //       1        1        1        1
        
        for(int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            
            if(ch >= 'a' && ch <= 'z') {
                // 원래 알파벳 - 'a' + n = 이동된 알파벳의 위치
                // 이동된 알파벳 위치 + 'a' = 이동된 알파벳
                // % 26 을 하는 이유는 z + 1 했을 때 a로 순환되게 하기 위해 
                ch = (char)((ch - 'a' + n) % 26 + 'a');
            }else if(ch >= 'A' && ch <= 'Z') {
                ch = (char)((ch - 'A' + n) % 26 + 'A');
            }
            
            answer += ch;
        }
        
        return answer;
    }
}