[알고리즘] 08. 문자열 처리 기초

[알고리즘] 08. 문자열 처리 기초

지난 글에서는 배열과 인덱스 처리에 대해 정리했습니다. 이번 글에서는 알고리즘 문제에서 배열만큼 자주 등장하는 문자열 처리에 대해 알아보겠습니다.

문자열은 문자들이 순서대로 모여 있는 데이터입니다. 이름, 단어, 문장, 숫자로 이루어진 문자열 등 다양한 형태로 문제에 등장합니다.

문자열 처리는 문자의 위치를 확인하고, 비교하고, 필요한 문자만 골라내는 과정입니다.

1. 문자열이란?

문자열은 여러 개의 문자가 순서대로 이어진 값입니다. Java에서는 문자열을 String 타입으로 다룹니다.

String name = "Java";
String word = "algorithm";
String sentence = "Hello World";

문자열도 배열처럼 순서가 있습니다. 그래서 각 문자의 위치를 인덱스로 접근할 수 있습니다.

문자열 J a v a
인덱스 0 1 2 3

배열과 마찬가지로 문자열의 인덱스도 0부터 시작합니다.


2. 문자열 길이 구하기

문자열의 길이는 length() 메서드로 구할 수 있습니다.

String word = "algorithm";

System.out.println(word.length());

위 문자열은 총 9개의 문자로 이루어져 있으므로 결과는 9입니다.

9

문자열 길이는 반복문을 돌릴 때 자주 사용됩니다.

String word = "Java";

for (int i = 0; i < word.length(); i++) {
    System.out.println(i);
}
배열은 length, 문자열은 length()를 사용합니다.

3. 특정 위치의 문자 가져오기

문자열에서 특정 위치의 문자를 가져올 때는 charAt() 메서드를 사용합니다.

String word = "Java";

System.out.println(word.charAt(0));
System.out.println(word.charAt(1));
System.out.println(word.charAt(2));
System.out.println(word.charAt(3));

출력 결과는 다음과 같습니다.

J
a
v
a

문자열의 마지막 문자는 길이보다 1 작은 인덱스에 있습니다.

String word = "Java";

char last = word.charAt(word.length() - 1);

System.out.println(last);

문자열 길이가 4라면 마지막 인덱스는 3입니다. 따라서 위 코드의 결과는 a입니다.

문자열의 마지막 인덱스는 문자열.length() - 1입니다.

4. 문자열 전체 순회하기

문자열 문제에서는 문자열을 처음부터 끝까지 확인하는 작업이 자주 나옵니다. 이때 반복문과 charAt()을 함께 사용합니다.

String word = "apple";

for (int i = 0; i < word.length(); i++) {
    char ch = word.charAt(i);
    System.out.println(ch);
}

위 코드는 문자열의 문자를 하나씩 꺼내서 출력합니다.

a
p
p
l
e

문자열 순회는 문자 개수 세기, 특정 문자 찾기, 문자열 뒤집기 같은 문제에서 기본이 됩니다.


5. 특정 문자 개수 세기

문자열에서 특정 문자가 몇 번 나오는지 세는 문제를 생각해보겠습니다. 예를 들어 문자열 안에 문자 a가 몇 개 있는지 확인해보겠습니다.

String word = "banana";

int count = 0;

for (int i = 0; i < word.length(); i++) {
    if (word.charAt(i) == 'a') {
        count++;
    }
}

System.out.println(count);

banana에는 a가 3개 들어 있으므로 결과는 3입니다.

3

이런 방식은 특정 알파벳, 숫자, 기호의 개수를 세는 문제에서 자주 사용됩니다.

목표 조건 예시
a 개수 세기 word.charAt(i) == 'a'
숫자 문자 찾기 ch >= '0' && ch <= '9'
대문자 찾기 ch >= 'A' && ch <= 'Z'
소문자 찾기 ch >= 'a' && ch <= 'z'

6. 문자열 비교하기

Java에서 문자열을 비교할 때는 ==가 아니라 equals()를 사용하는 것이 안전합니다.

String a = "java";
String b = "java";

System.out.println(a.equals(b));

두 문자열의 내용이 같으므로 true가 출력됩니다.

true

문자열 비교에서 ==는 문자열의 내용이 아니라 참조 위치를 비교할 수 있습니다. 그래서 알고리즘 문제에서는 문자열 내용 비교에 equals()를 사용하는 습관을 들이는 것이 좋습니다.

String input = "YES";

if (input.equals("YES")) {
    System.out.println("확인");
}
문자열 내용 비교는 equals()를 사용합니다.

7. 대소문자 변환하기

문자열 문제에서는 대문자와 소문자를 변환해야 하는 경우도 많습니다. Java에서는 toUpperCase()toLowerCase()를 사용할 수 있습니다.

String word = "Java";

System.out.println(word.toUpperCase());
System.out.println(word.toLowerCase());

출력 결과는 다음과 같습니다.

JAVA
java

대소문자를 구분하지 않고 비교해야 할 때는 둘 다 같은 형태로 바꾼 뒤 비교하면 됩니다.

String a = "Java";
String b = "java";

if (a.toLowerCase().equals(b.toLowerCase())) {
    System.out.println("같은 단어입니다.");
}

이렇게 하면 Java와 java를 같은 값으로 처리할 수 있습니다.


8. 문자열 뒤집기

문자열을 뒤집는 문제도 자주 등장합니다. 가장 기본적인 방법은 뒤에서부터 한 글자씩 읽어서 새로운 문자열에 붙이는 것입니다.

String word = "hello";

String result = "";

for (int i = word.length() - 1; i >= 0; i--) {
    result += word.charAt(i);
}

System.out.println(result);

출력 결과는 다음과 같습니다.

olleh

다만 문자열을 반복해서 더하는 방식은 데이터가 많아지면 비효율적일 수 있습니다. 이럴 때는 StringBuilder를 사용하는 것이 좋습니다.

String word = "hello";

StringBuilder sb = new StringBuilder();

for (int i = word.length() - 1; i >= 0; i--) {
    sb.append(word.charAt(i));
}

System.out.println(sb.toString());

StringBuilder는 문자열을 여러 번 이어 붙일 때 자주 사용됩니다.


9. 문자열에 특정 값이 포함되어 있는지 확인하기

문자열 안에 특정 문자열이 포함되어 있는지 확인할 때는 contains()를 사용할 수 있습니다.

String sentence = "I like Java";

System.out.println(sentence.contains("Java"));
System.out.println(sentence.contains("Python"));

출력 결과는 다음과 같습니다.

true
false

contains()는 특정 단어가 포함되어 있는지 확인하는 문제에서 유용합니다.

다만 문자 하나씩 직접 검사해야 하는 문제라면 반복문과 charAt()을 사용하는 방식이 더 적합할 수 있습니다.


10. 문자열을 문자 배열로 바꾸기

문자열을 문자 배열처럼 다루고 싶을 때는 toCharArray()를 사용할 수 있습니다.

String word = "code";

char[] arr = word.toCharArray();

for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

출력 결과는 다음과 같습니다.

c
o
d
e

문자열 자체는 직접 수정하기 어렵기 때문에, 문자를 바꿔야 하는 문제에서는 char 배열로 변환해서 처리하는 경우가 많습니다.

String word = "code";

char[] arr = word.toCharArray();

arr[0] = 'm';

String result = new String(arr);

System.out.println(result);

출력 결과는 mode입니다.

mode

11. 문자열 처리에서 자주 하는 실수

문자열 문제를 풀 때는 아래 실수를 조심해야 합니다.

  • 문자열 인덱스가 0부터 시작한다는 점을 잊는 경우
  • 마지막 문자를 word.charAt(word.length())로 접근하는 경우
  • 문자열 비교에 ==를 사용하는 경우
  • 문자와 문자열을 혼동하는 경우
  • 반복문 범위를 잘못 작성하는 경우
  • 문자열을 너무 많이 더해서 비효율이 생기는 경우

특히 문자와 문자열은 다릅니다. 문자 하나는 작은따옴표를 사용하고, 문자열은 큰따옴표를 사용합니다.

char ch = 'a';
String str = "a";

둘은 비슷해 보이지만 타입이 다르므로 상황에 맞게 사용해야 합니다.

문자 하나는 char, 여러 문자의 모음은 String입니다.

12. 정리

이번 글에서는 문자열 처리 기초를 정리했습니다.

  • 문자열은 문자들이 순서대로 모여 있는 데이터이다.
  • 문자열 인덱스는 배열처럼 0부터 시작한다.
  • 문자열 길이는 length()로 구한다.
  • 특정 위치의 문자는 charAt()으로 가져온다.
  • 문자열 내용 비교는 equals()를 사용한다.
  • 대소문자 변환은 toUpperCase(), toLowerCase()를 사용한다.
  • 문자열을 자주 이어 붙일 때는 StringBuilder를 고려한다.
  • 문자를 수정해야 한다면 char 배열 변환을 사용할 수 있다.

문자열 문제는 처음에는 단순해 보이지만, 인덱스와 조건 처리가 조금만 복잡해져도 실수가 자주 발생합니다.

문자열 처리의 핵심은 인덱스를 정확히 다루고, 문자와 문자열을 구분하는 것입니다.

다음 글 예고

다음 글에서는 문자열 자르기와 비교에 대해 알아보겠습니다.

substring(), split(), equals(), compareTo()처럼 문자열 문제에서 자주 사용하는 기능을 예제와 함께 정리해보겠습니다.