
내가 생각했을때 문제에서 원하는부분
The first line of input contains a single integer T, denoting the number of test cases.
The first and only line of each test case contains a string s.
For each test case, output a single line containing an integer — the minimum number of flips required.
내가 이 문제를 보고 생각해본 부분
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
표준 입력(System.in)으로부터 효율적으로 데이터를 읽어들이기 위한 BufferedReader 객체를 생성한다.
한 줄씩 읽는 readLine() 메서드를 사용하기 위함이다.
StringBuilder sb = new StringBuilder();
StringBuilder는 여러 개의 문자열을 효율적으로 합치고 저장하기 위해 사용된다.
int T = Integer.parseInt(br.readLine());
테스트 케이스의 총 개수 T를 입력받아 정수로 변환한다.
for(int i = 0; i < T; i++) { ... }
T번 반복하여 각 테스트 케이스를 처리하는 반복문이다.
String s = br.readLine();
각 반복마다 풍선 색깔 정보를 담은 문자열 s를 한 줄씩 읽어온다.
if(s == null) { sb.append(0).append('\n'); continue; }
br.readLine()은 파일의 끝(End Of File, EOF)에 도달했을 때 null을 반환할 수 있다.
이런 경우를 대비하여 s가 null이면 0을 결과에 추가하고 다음 반복으로 건너뛰도록 처리한다.
이 문제의 조건(1 <= n)을 감안할 때 발생할 일은 거의 없지만, 더 견고한 코드를 만들었다고 볼 수 있다.
s = s.trim();
trim() 메서드는 문자열 양 끝의 공백(스페이스, 탭, 줄 바꿈 문자 등)을 제거한다.
만약 입력 문자열 끝에 의도치 않은 공백이 포함될 경우를 대비하여 trim()을 사용하면 정확한 문자열 내용만으로 'a'와 'b'의 개수를 셀 수 있다.
int countA = 0; int countB = 0;
각 테스트 케이스마다 'a'와 'b' 풍선의 개수를 세기 위한 변수들을 0으로 초기화한다.
for(char c : s.toCharArray()) { ... }
문자열 s를 문자 배열로 변환하여 각 문자를 순회한다.
if(c == 'a') { countA++; } else if (c == 'b') { countB++; }
순회 중인 문자가 'a'이면 countA를, 'b'이면 countB를 1 증가시킨다.
이전 else 대신 else if (c == 'b')로 명확하게 조건을 지정해준다.
문제 조건 상 입력에는 'a'와 'b'만 존재하겠지만, 명시적으로 'b'를 확인하는 것은 다른 예상치 못한 문자가 들어올 경우에 대비할 수 있다.
이 문제에서는 'a'와 'b' 외 다른 문자는 무시하게 된다.
sb.append(Math.min(countA, countB)).append('\n');
계산된 countA와 countB 중 더 작은 값(Math.min)을 StringBuilder에 추가한다.
append('\n')을 사용하여 각 결과 뒤에 줄 바꿈 문자를 추가한다.
이렇게 해야 각 테스트 케이스의 결과가 새로운 줄에 출력된다.
이것이 System.out.println()의 역할을 대체하는 부분이다.
System.out.print(sb.toString());
모든 테스트 케이스의 결과가 StringBuilder에 누적되면, sb.toString()을 호출하여 하나의 큰 문자열로 변환하고 System.out.print()를 사용해 한 번에 표준 출력으로 내보낸다.
println 대신 print를 사용하는 이유는 StringBuilder에 이미 줄 바꿈 문자가 포함되어 있기 때문이다.
br.close();
마지막으로, 사용한 BufferedReader 자원을 해제한다.
코드로 구현
package baekjoon.baekjoon_31;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
// 백준 30156번 문제
public class Main1241 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 표준 입력을 효율적으로 읽기 위한 BufferedReader 생성
StringBuilder sb = new StringBuilder(); // 결과를 한 번에 출력하기 위한 StringBuilder 생성
int T = Integer.parseInt(br.readLine()); // 첫 번째 줄에서 테스트 케이스의 개수 T를 읽습니다.
// 테스트 케이스 수만큼 반복 처리합니다.
for (int i = 0; i < T; i++) {
// 각 테스트 케이스의 문자열 S를 한 줄 읽습니다.
String s = br.readLine();
// 만약 입력이 비어 있거나(EOF 등) null이 반환되면 0을 추가하고 다음 케이스로 넘어갑니다.
if (s == null) {
sb.append(0).append('\n');
continue;
}
// 앞뒤 불필요한 공백을 제거합니다. (예: 라인 끝 공백)
s = s.trim();
// 'a'와 'b'의 개수를 저장할 변수 초기화
int countA = 0;
int countB = 0;
// 문자열 s의 각 문자를 순회하며 'a'와 'b'의 발생 횟수를 센다.
// 'a'이면 countA 증가, 'b'이면 countB 증가, 그 외 문자는 무시한다.
for (char c : s.toCharArray()) {
if (c == 'a') {
countA++;
} else if (c == 'b') {
countB++;
}
}
// 모든 풍선을 같은 색으로 만들기 위해 최소로 재칠해야 하는 횟수는
// 'a'와 'b' 중 더 적은 쪽의 개수(즉 Math.min(countA, countB))입니다.
// 그 값을 StringBuilder에 한 줄로 추가합니다.
sb.append(Math.min(countA, countB)).append('\n');
}
// 누적한 결과를 한 번에 출력합니다.
System.out.print(sb.toString());
// 사용한 스트림을 닫아 리소스를 해제합니다.
br.close();
}
}
코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.