3 minute read


Input-1
“try hello world” Output-1
“TrY HeLlO WoRlD”

Input-2
“ABC aBc abC “ Output-2
“Abc Abc Abc “

문제 풀이

문제 설명을 보면 주어진 문자열은 한개 이상의 단어로 구성되어 있으며, 각 단어는 하나 이상의 공백문자로 구분된다고 한다.
각 단어별로 짝수번째 인덱스의 단어는 대문자로, 홀수번째 인덱스의 단어는 소문자로 변경된 문자열을 반환해야 한다.
여기서 핵심은 “각 단어는 하나 이상의 공백문자로 구분된다.” 이라고 생각한다.

그럼 공백문자를 기준으로 문자열을 잘라 각 단어들에 접근하는 방법을 알아보자.

1
2
3
String str = "try hello world";
String[] arr = str.split(" ");
for(String s : arr) System.out.println(s);

먼저 java.lang.String 클래스의 split() 메서드의 regex 인자에 “ “ 값을 넣어준다면 어떤 결과가 나올까?

1
2
3
4
// "try hello world"
try
hello
world

공백값을 기준으로 문자열을 잘랐기에 위와 같은 문자열 배열을 이룰 것이다.
만약 “try hello world” 라는 입력값의 경우는 단어 사이에만 공백이 존재하기에 위 방법으로 각 단어들에 접근이 가능하다.

하지만 “try hello world” 라는 입력값의 경우 단어 사이에 여러개의 공백이 존재한다.

1
2
3
4
// "try  hello    world"
try
hello
world

위 방법으로는 각 단어 사이의 존재하는 여러개의 공백문자를 찾아낼 수 없다.
우리가 원하는 것은 각 단어 사이의 공백문자까지 포함한 문자열을 반환하는 것이다.

어떻게 단어 사이의 공백문자를 찾을까?

해답은 split() 메서드에 있다. split() 메서드는 사용하는 방식이 2가지가 있다.

  • public String[] split(String regex)
  • public String[] split(String regex, int limit)

    regex라는 문자를 구분자로, limit는 나눠지는 배열의 길이를 제한한다.

나는 2번째 방식으로 limit 인자를 추가로 전달하여 문제를 해결하려 한다.
또한 limit에 어떤 값이 들어가냐에 따라 3가지로 나뉜다.

  1. limit가 0일 경우
    단순하게 split(String regex) 메서드를 사용하는 것과 같은 기능을 한다.
    split(“ “,0)과 split(“ “)은 동일하다.

  2. limit가 양수일 경우
    limit에 지정한 수만큼 배열의 크기가 결정된다.(String[]의 크기)
    1
    2
    3
    
    String str = "a,b,c,,,";
    String[] arr = str.split(",", 2);
    // output: ["a", "b,c,,"]
    

    예를 들어 “a,b,c,,,”라는 문자열이 있으면 [“a”, “b,c,,”]로 저장된다.

  3. limit가 음수일 경우
    limit가 음수일 경우 구분자에 따라 전부 나눠주며 공백 또한 데이터로 보고 배열에 저장된다.
    1
    2
    3
    
    String str = "a,b,c,,,";
    String[] arr = str.split(",", -1);
    // output: ["a", "b", "c", "", "" ,""]
    

    예를들어 “a,b,c,,,”라는 문자열이 있으면 [“a”, “b”, “c”, “”, “”, ““]로 저장된다.
    limit에 음수값을 넣어 주어진 문자열에 있는 각 단어사이의 공백문자가 들어간 경우를 해결할 수 있게 된다.

그러면 split() 메서드에 limit를 음수값으로 넣어 주어진 문자열의 각 단어 사이의 공백문자도 포함하여 찾을 수 있다.

1
2
String[] str = s.split(" ", -1); // 주어진 문자열을 공백문자 기준으로 공백문자를 포함하여 배열에 저장한다.
// input:"try  hello   world", output:["try", " ", "hello", " ", "world"]

공백문자를 기준으로 잘라 배열의 저장하니 공백문자 개수가 -1개임을 확인하였다.
이제 각 단어별로 짝수번째 인덱스인지, 홀수번째 인덱스인지를 확인하여 대소문자로 치환하는 코드를 작성해보자.

1
2
3
4
5
6
for(int i=0; i<str.length; i++) {
    for(int j=0; j<str[i].length(); j++) {
        if(j%2 == 0) sb.append(String.valueOf(str[i].charAt(j)).toUpperCase());
        else sb.append(String.valueOf(str[i].charAt(j)).toLowerCase());      
    }
}
1
2
3
4
5
6
// input:"try  hello  world"
try -> TrY

hello -> HeLlO

world -> WoRlD

위와 같이 배열만큼 반복문을 돌며 짝수번째 인덱스는 대문자, 홀수번째 인덱스는 소문자로 치환되도록 작성하였다.

1
2
3
4
5
6
7
8
9
10
11
// input:"try  hello  world"
i=0, str[i]="try"
// sb="TrY"
i=1, str[i]=" "
// sb="TrY "
i=2, str[i]="hello"
//sb="TrY  HeLlO"
i=3, str[i]=" "
//sb="TrY  HeLlO "
i=4, str[i]="world"
//sb="TrY  HeLlO  WoRlD"

또한 입력값과 동일한 공백문자를 포함해야 하는데 현재는 공백값이 -1개로 포함되어 있기에 공백문자도 추가로 포함시켜야 한다.

1
2
3
4
5
6
7
for(int i=0; i<str.length; i++) {
    for(int j=0; j<str[i].length(); j++) {
        if(j%2 == 0) sb.append(String.valueOf(str[i].charAt(j)).toUpperCase());
        else sb.append(String.valueOf(str[i].charAt(j)).toLowerCase());      
    }
    if(i < str.length-1) sb.append(" "); // i가 배열의 길이-1보다 작을 때 공백문자 추가
}

대소문자 치환과 공백문자를 추가로 포함시킨 코드를 작성하였다.


작성코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.*;

class Solution {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        solution(s);
    }

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

회고

  • java.lang.String 클래스에서 split()메서드의 limit 인자를 통해 주어진 문자열의 구분자를 허용하도록 할 수 있음을 알게되었다.
  • 문제 설명에서 모든 제약사항을 알려주지 않으니 나름대로 꼼꼼히 제약사항을 파악할줄 알아야 함을 느꼈다.