코딩 테스트에서 문자열을 효율적으로 다루는 방법은 시간 초과를 피하는 핵심 전략입니다. String, StringBuilder, 그리고 문자열과 배열의 관계를 제대로 이해하면 성능을 크게 향상할 수 있습니다.
String과 StringBuilder의 차이점String: 불변(Immutable) 객체 🧊String은 한 번 생성되면 그 내용을 변경할 수 없습니다. 문자열을 수정하거나 이어붙일 때마다 새로운 String 객체가 생성됩니다. 이 때문에 반복문에서 + 연산을 사용하면 수많은 객체가 만들어져 메모리 낭비와 함께 성능이 급격히 저하됩니다. 이는 코딩 테스트에서 **시간 초과(Time Limit Exceeded)**의 주요 원인이 됩니다.
StringBuilder: 가변(Mutable) 객체 ✨StringBuilder는 기존 객체의 메모리 공간을 재활용하며 문자열을 추가, 수정, 삭제할 수 있습니다. 문자열을 자주 조작하는 코딩 테스트 환경에 매우 적합하며, 반복적인 문자열 작업에 필수적입니다.
✅ 비효율적인 String vs 효율적인 StringBuilder
// 비효율적인 String 사용
String str = "";
for (int i = 0; i < 1000; i++) {
str += "a"; // 매 반복마다 새로운 String 객체 생성
}
// 효율적인 StringBuilder 사용
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("a"); // 기존 객체에 계속 추가
}
StringBuilder 주요 메서드StringBuilder 객체를 다룰 때 자주 사용하는 메서드들입니다.
| 메서드 | 설명 | 예시 |
|---|---|---|
append() | 다양한 타입의 데이터를 문자열로 변환하지 않고 바로 추가합니다. | sb.append(123); sb.append("World"); |
length() | StringBuilder에 담긴 문자열의 길이를 반환합니다. | if (sb.length() == 0) { ... } |
charAt() | 특정 인덱스의 문자를 반환합니다. | if (sb.charAt(0) == '0') { ... } |
toString() | StringBuilder 객체를 String 타입으로 변환합니다. 최종 결과를 반환할 때 사용합니다. | String result = sb.toString(); |
String.repeat() (Java 11 이상)vs StringBuilder.append()
자바 11 이상에서 제공되는 메서드로, 특정 문자열을 지정된 횟수만큼 반복할 수 있어 코드를 간결하게 만들어줍니다.
repeat()는 내부적으로 StringBuilder를 사용해요. 예를 들어, str.repeat(5)를 호출하면 자바는 내부적으로 StringBuilder를 생성하고, append()를 5번 호출한 뒤, 최종적으로 toString()을 호출해 새로운 문자열을 만듭니다.
// 예시: 5번 반복하여 "abcabcabcabcabc" 생성
String repeatedString = "abc".repeat(5);
repeat()는 내부적으로 StringBuilder를 사용해 문자열을 이어붙이는 것과 비슷하게 동작하므로, 성능 면에서도 효율적입니다.
charAt() vs toCharArray(): 성능과 메모리의 차이문자열의 각 문자에 접근하는 두 가지 방법에는 성능과 메모리 사용량에 큰 차이가 있습니다. 코딩 테스트에서 O(N)과 O(1)의 차이는 결과에 큰 영향을 미칩니다.
| 특징 | charAt(j)🥇 | toCharArray() |
|---|---|---|
| 작동 방식 | 문자열에서 j 인덱스의 문자를 직접 반환합니다. | 문자열의 모든 문자를 새로운 char 배열로 복사합니다. |
| 메모리 사용 | 추가 메모리 할당이 거의 없어 O(1) | 문자열 길이만큼의 메모리를 추가로 사용해 O(N) |
| 성능 | 필요한 문자 하나만 접근하므로 매우 빠릅니다. | 배열 전체를 생성해야 하므로 상대적으로 느립니다. |
✅ toCharArray() 사용 시 주의점
반복문 안에서 toCharArray()를 사용하면 매번 새로운 배열이 생성되어 메모리 낭비를 초래합니다.
// 비효율적인 toCharArray() 사용
for (int i = 0; i < wallpaper.length; i++) {
char[] wallpaperJ = wallpaper[i].toCharArray(); // ⚠️ 매 반복마다 배열 생성
for (int j = 0; j < wallpaper[i].length(); j++) {
if (wallpaperJ[j] == '#') {
// ...
}
}
}
charAt()를 사용하면 새로운 배열을 만들 필요 없이 원래 문자열에서 바로 문자에 접근하므로 메모리 효율성과 시간 효율성 모두 높아집니다.
문자 '0'~'9'를 실제 정수 0~9로 변환하는 기술입니다. 배열의 인덱스로 활용할 때 매우 유용합니다.
// 예시: 문자 '5'를 정수 5로 변환하여 배열의 5번 인덱스를 증가
int[] count = new int[10];
char num = '5';
count[num - '0']++;
코딩테스트 풀 때 별 생각 없이 다른 사람들이 그렇게 하니까, 모범답안처럼 썼던 것들에 대해서 다시 이유를 살펴보니 재밌기도 하고 부끄럽기도 하고 그렇네요...
잘 보고 갑니다~!!