문제
백준 2941번
주어진 문자열이 몇 개의 크로아티아 알파벳으로 이루어져있는지 출력하는 문제
풀이 1) substring() 사용
연속된 두 개의 문자가 c=, c-, d-, lj, nj, s=, z=이면 하나로 세고,
연속된 세 개의 문자가 dz=이면 하나로 세어지도록 코드를 짜야 한다.
문자열을 입력받고, 알파벳의 갯수를 저장할 count 변수를 선언하고 0으로 초기화한다.
아래 세 경우를 str.length()번 반복한다.
- 조건 1
문자열의 인덱스를 초과하지 않는 범위에서 연속하는 두 문자로 이루어진 문자열을 추출한다.
추출된 문자열이 c=, c-, ...와 같다면 다음 알파벳은 1개 뛰어넘고 세어야 하므로 i를 1증가시킨다. - 조건 2
문자열의 인덱스를 초과하지 않는 범위에서 연속하는 세 문자로 이루어진 문자열을 추출한다.
추출된 문자열이 dz=와 같다면 다음 알파벳은 2개 뛰어넘고 세어야 하므로 i를 2증가시킨다. - count 1증가
count를 출력한다.
코드
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
//연속된 두 개의 문자가 c= c- d- lj nj s= z=이면 하나로 센다.
//연속된 세 개의 문자가 dz=이면 하나로 센다.
String str = br.readLine();
int count = 0;
for(int i=0; i<str.length(); i++) {
if(i<str.length()-1) {
String s1 = str.substring(i,i+2);
if(s1.equals("c=")||s1.equals("c-")||s1.equals("d-")||s1.equals("lj")||s1.equals("nj")||s1.equals("s=")||s1.equals("z=")) {
i++;
}
}
if(i<str.length()-2) {
String s2 = str.substring(i, i+3);
if(s2.equals("dz=")) {
i+=2;
}
}
count++;
}
bw.write(count+" ");
bw.close();
}
}
풀이 2) StringBuilder 사용
로직은 풀이 1과 같으나, StringBuilder을 사용할 때는 주의할 점이 있다.
StringBuilder객체를 한 번 선언한 후 그 객체에 계속 append하면 뒤에 연달아 붙는다는 것에 유의하자.
처음에 StringBuilder 객체를 for문 밖에 선언해서 사용했는데, append 문제로 계속 오답처리가 되었다.
그래서 i++ 또는 i+=2가 실행된 다음에 객체를 비우는 메서드를 추가해보았는데 여전히 해결되지 않았다.
for문을 다시 실행할 때마다 StringBuilder 객체가 새로 생성되도록 선언문을 for문 아래로 옮겼더니 해결되었다.
for문 내에서도 StringBuilder 객체를 하나만 사용하려면 연속된 두 문자를 비교한 후 객체를 비우고 다시 append하여 연속된 세 문자를 비교해야한다는 점도 잊지 말자.
나는 StringBuilder객체 초기화가 안 먹혀서 그냥 별도의 객체를 두 번 생성해서 사용했다.
그러나 StringBuilder 객체를 매번 새로 생성해서 사용할 거면 StringBuilder의 이점을 무시한 구현방법 아닐까?
그리고 성능면에서도 안 좋지 않을까? 라는 고민과 함께, 내일은 String과 StringBuilder에 대한 포스팅을 좀 더 보완해볼 생각이다. 포스팅을 마치고 나면 해당 코드도 업그레이드시킬 수 있지 않을까..?
코드
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args)throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
//연속된 두 개의 문자열이 c= c- d- lj nj s= z=이면 하나로 센다.
//연속된 세 개의 문자열이 dz=이면 하나로 센다.
String str = br.readLine();
int count = 0;
for(int i=0; i<str.length(); i++) {
StringBuilder sb1 = new StringBuilder();
if(i<str.length()-1) {
sb1.append(str.charAt(i));
sb1.append(str.charAt(i+1));
String s = sb1.toString();
if(s.equals("c=")||s.equals("c-")||s.equals("d-")||s.equals("lj")||s.equals("nj")||s.equals("s=")||s.equals("z=")) {
i++;
}
}
StringBuilder sb2 = new StringBuilder();
if(i<str.length()-2) {
sb2.append(str.charAt(i));
sb2.append(str.charAt(i+1));
sb2.append(str.charAt(i+2));
String s = sb2.toString();
if(s.equals("dz=")) {
i+=2;
}
}
count++;
}
bw.write(count+" ");
bw.close();
}
}
위 - 풀이 1
아래 - 풀이 2
substring보다 StringBuilder가 성능이 더 좋다.
Note
==
와equals()
- String은 class이므로
==
연산자를 사용하면 주소값이 비교된다. 값 자체를 비교하려면equals()
메서드를 사용해야 한다.
- String은 class이므로
- StringBuilder 객체 사용 시 append에 유의하자. 아무것도 저장되지 않은 새로운 공간이 필요하다면 객체를 비우거나 새로 선언해야 한다.
- if문이나 for문 안의 조건문을 계속 실수하게 된다. 더 신경쓰자
'BOJ' 카테고리의 다른 글
[백준 25206번/JAVA] 너의 학점은 (0) | 2024.03.13 |
---|---|
[백준 1316번/JAVA] 그룹 단어 체커 (0) | 2024.03.13 |
[백준 1157번/JAVA] 단어 공부 (0) | 2024.03.11 |
[백준 10988번/JAVA] 팰린드롬인지 확인하기 (0) | 2024.03.11 |
[백준 2224번/JAVA] 별 찍기 - 7 (0) | 2024.03.11 |