[알고리즘] Programmers_#12930

Yuri·2025년 1월 4일

코딩테스트

목록 보기
8/9

🗒️ CodeKata 진행 중 어려웠던 부분을 정리하여 기록합니다.

12930. 이상한 문자 만들기

문제 설명

문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.

제한 사항

문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야합니다.
첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 합니다.

입출력 예

sreturn
“try hello world”“TrY HeLlo WoRlD”

입출력 예 설명

"try hello world"는 세 단어 "try", "hello", "world"로 구성되어 있습니다. 각 단어의 짝수번째 문자를 대문자로, 홀수번째 문자를 소문자로 바꾸면 "TrY", "HeLlO", "WoRlD"입니다. 따라서 "TrY HeLlO WoRlD" 를 리턴합니다.


▶︎ 풀이

  1. 반례를 추가하여 조건 확인
sreturn
“TRy HElLo  WORLD ”“TrY HeLlO  WoRlD ”

1) 하나 이상의 공백문자로 구분되어 있는 문자열 s의 return에는 원래 문자열 s와 같이 공백문자가 있어야 한다. s의 HElLo  WORLD 사이에는 두 개의 공백문자가 있고 return에서도 두 개의 공백문자가 있어야 한다.

2) 문자열 s의 마지막에 공백문자가 있을 수 있다. 마지막의 공백문자는 return에도 있어야 한다.

아래의 기존코드는 반례를 통과하지 못한다.

▶︎ 기존코드 (오답)

알고리즘 문제를 풀 때의 주의사항 → 모든 조건은 문제 안에 있다!
나의 경우 해당 문제를 지난번에 풀었던 LeetCode_#151 번과 비슷한 문제로 착각했던 것이다. 하지만 당연히 이 문제는 지난 문제와 주어진 조건이 달라 주의가 필요하다. 항상 모든 문제를 꼼꼼히 읽어볼 것!

public static String solution(String s) {
        StringBuilder sb = new StringBuilder();
        String[] strs = s.split("\\s+");
        for (String str : strs) {
            for(int i = 0; i < str.length(); i++) {
                if(i % 2 == 0) {
                    sb.append(str.toUpperCase().charAt(i));
                } else {
                    sb.append(str.toLowerCase().charAt(i));
                }
            }
            sb.append(" ");
        }
        return sb.toString().trim();
    }

▶︎ 개선사항

  1. split(String regex, int limit)
  • regex - 구분 정규 표현식
  • limit - 패턴이 적용되는 횟수를 제어
    • limit > 0: 패턴이 최대 한도(1회)로 적용되며, 배열의 크기가 limit 보다 크지 않다. 배열의 마지막 항목에는 마지막으로 일치하는 구분 기호(regex)를 초과하는 모든 입력이 포함된다.
    • 0: 패턴은 가능한 많이 적용되고 배열의 길이는 제한되지 않으며 뒤에 오는 빈 문자열은 삭제된다.
    • limit < 0: 패턴은 가능한 많이 적용되고 배열의 길이는 제한되지 않는다.

⇒ 문제의 조건을 만족하려면, 공백 문자를 기준으로 구분(단, 공백문자가 여러 개 있더라도 하나로 합쳐지지 않음)하므로 regex\\s, 가장 마지막에 공백문자가 있을 경우 빈 문자열이 삭제되지 않도록 limit로는 -1값을 파라미터로 전달한다.

  1. 문자열 사이에 공백문자 추가
    공백문자를 기준으로 split 하였으므로 각 문자열을 대문자, 소문자 변환한 뒤 다시 하나의 문자열로 합칠 때 중간에 공백문자를 추가하여 붙여야 한다. 이 때, 가장 마지막의 문자열 뒤에는 공백문자를 추가하지 않는다.
    ⚠️ trim을 사용하면 기존 문자열에 공백문자가 있을 경우 해당 공백문자까지 지워지기 때문에 반복문 안에서 조건을 주어 추가여부를 판단한다.

▶︎ 수정코드 (정답)

class Solution {
    public String solution(String s) {
        StringBuilder sb = new StringBuilder();
        String[] strs = s.split("\\s", -1);
        for (int i = 0; i<strs.length; i++) {
            String str = strs[i];
            for(int j = 0; j < str.length(); j++) {
                if(j % 2 == 0) {
                    sb.append(str.toUpperCase().charAt(j));
                } else {
                    sb.append(str.toLowerCase().charAt(j));
                }
            }
            if( i != strs.length - 1 ) {
                sb.append(" ");                  
            }
        }
        return sb.toString();
    }
}

🧸) 정답까지 나의 과정

기존에 풀었던 문제를 응용하는 것도 좋지만 요구사항에 대한 정의를 꼼꼼히 살펴봐야한다..

profile
안녕하세요 :)

0개의 댓글