개발자는 기록이 답이다
[백준/BOJ][Java][2675] 문자열 반복 본문
2023.08.21 - [Java] - Java, String의 constant pool과 Heap의 차이
https://www.acmicpc.net/problem/2675
내가 푼 풀이
- 3중 for문 말고 다른 방법을 생각해보려고 했는데, 모르겠어서 다른 사람꺼 보고 공부하려고 했더니 전부 중첩 반복문 쓰신 것 같다.
- 자바 11부터 repeat()함수가 있다고 하는데, 나는 자바 8로 하는 중이라 for문을 하나 더 쓸 수 밖에 없었다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
String str = br.readLine();
String[] split = str.split(" ");
StringBuilder sb = new StringBuilder();
for (int j = 0; j < split[1].length(); j++) {
int count = Integer.parseInt(split[0]);
for (int k = 0; k < count; k++) {
sb.append(split[1].charAt(j));
}
}
System.out.println(sb);
}
}
}
메모리 | 시간 | 언어 | 코드 길이 |
11488KB | 84ms | Java8 | 787B |
다른 사람 풀이 1
1. BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 에 대해서 알게 되었다.
- 그리고 BufferedWriter를 쓰려면 flush(), close()함수를 꼭 써주자.
BufferedWriter는 출력을 버퍼에 모아두었다가 한 번에 출력하는 역할을 하는 Java의 클래스입니다. BufferedWriter를 사용하는 이유는 프로그램의 효율성과 성능을 향상시키기 위해서입니다.
표준 출력(System.out)으로 직접 출력할 때는 매번 출력할 때마다 입출력 작업이 수행되기 때문에 속도가 느릴 수 있습니다. 반면, BufferedWriter를 사용하면 출력을 임시로 저장하는 버퍼에 쌓아두었다가 버퍼가 가득 찼거나 작업이 끝나면 한 번에 출력을 수행합니다. 이로써 입출력 작업의 횟수를 줄이고 프로그램의 성능을 향상시킬 수 있습니다.
따라서 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));는 표준 출력을 버퍼링하여 프로그램의 출력 성능을 개선하기 위해 사용된 것입니다. 출력 작업이 빈번하게 발생하는 상황에서 특히 유용합니다.
1. bw.flush(): 버퍼에 남아있는 데이터를 강제로 출력합니다. 이를 호출하지 않으면 버퍼에 쌓아둔 데이터가 출력되지 않을 수 있습니다. 프로그램이 끝나기 전에 모든 출력이 확실하게 처리되도록 하기 위해서 flush()를 사용하는 것이 좋습니다.
2. bw.close(): BufferedWriter를 사용한 후에는 반드시 닫아주어야 합니다. 이 메서드는 내부적으로 flush()를 호출하여 남아있는 버퍼의 데이터를 모두 출력하고 자원을 정리합니다. 만약 close()를 호출하지 않으면 버퍼가 비워지지 않고 남을 수 있으며, 이는 원하지 않는 동작을 초래할 수 있습니다.
따라서 BufferedWriter를 사용한 후에는 코드 마지막에 bw.flush()와 bw.close()를 호출하여 데이터를 확실하게 출력하고 자원을 해제하는 것이 좋습니다.
2. 메소드 분리로 가독성이 좋아지긴 했지만, setData() 메서드 내에서 중첩된 반복문을 사용하여 resultArray 배열을 채우는 방식으로 구현되어있어서 중첩 반복문을 직접 사용하여 문자를 출력했던 나의 방식과 비슷한 것 같다.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main {
private static int T;
private static int repeat;
private static char[] chArray, resultArray;
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
T = Integer.parseInt(br.readLine());
for(int t = 1 ; t <= T ; t++) {
StringTokenizer st = new StringTokenizer(br.readLine());
repeat = Integer.parseInt(st.nextToken());
chArray = st.nextToken().toCharArray();
resultArray = new char[repeat*chArray.length];
setData();
print(bw);
}
bw.flush();
bw.close();
}
private static void setData() {
int index = 0;
for(int i = 0 ; i < chArray.length ; i++) {
for(int j = 0 ; j < repeat ; j++) {
resultArray[index++] = chArray[i];
}
}
}
private static void print(BufferedWriter bw) throws Exception {
for(int i = 0 ; i < resultArray.length ; i++) {
bw.write(String.valueOf(resultArray[i]));
}
bw.newLine();
}
}
메모리 | 시간 | 언어 | 코드 길이 |
13000KB | 64ms | Java8 | 1287B |
다른 사람 풀이 1을 응용한 풀이1
- 코드 길이는 길어지지만 split()함수 대신에 StringTokenizer을 사용하는게 훨씬 더 속도가 빠른 것 같다.
- 공백을 기준으로 앞에 있는 입력값은 숫자로 받고, 뒤에 있는 입력값은 toCharArray()로 받으면 되는것 같다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
private static int repeat;
private static char[] chArray;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
repeat = Integer.parseInt(st.nextToken()); // 3
chArray = st.nextToken().toCharArray(); // [A, B, C]
StringBuilder sb = new StringBuilder();
for (int j = 0; j < chArray.length; j++) {
for (int k = 0; k < repeat; k++) {
sb.append(chArray[j]);
}
}
System.out.println(sb);
}
}
}
메모리 | 시간 | 언어 | 코드 길이 |
11320KB | 76ms | Java8 | 938B |
다른 사람 풀이 1을 응용한 풀이2
- BufferedWriter를 사용하는 코드로 수정해봤는데, 성능이 좋아진것 같진 않은데, 입출력의 양이 많지 않아서 그런걸까?
import java.io.*;
import java.util.StringTokenizer;
public class Main {
private static int repeat;
private static char[] chArray;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
repeat = Integer.parseInt(st.nextToken()); // 3
chArray = st.nextToken().toCharArray(); // [A, B, C]
for (int j = 0; j < chArray.length; j++) {
for (int k = 0; k < repeat; k++) {
bw.write(chArray[j]);
}
}
bw.newLine();
}
bw.flush();
bw.close();
}
}
메모리 | 시간 | 언어 | 코드 길이 |
11396KB | 76ms | Java8 | 916B |
다른 사람 풀이 2
- 내가 푼 풀이랑 비슷한데, 마지막에 sb.delete(0, sb.length());가 있다. 이것의 역할과 사용 목적은 무엇일까?
StringBuilder 객체 내의 특정 문자열 부터 데이터를 삭제하는 작업을 수행하는 코드입니다.
delete(start, end)는 StringBuilder에 저장된 문자열의 start Index에서 end Index 직전까지 삭제합니다. 즉, 삭제 대상에서 start는 포함하며, end는 포함하지 않습니다.
1. 이전 테스트 케이스의 결과 삭제: 코드는 각 테스트 케이스마다 문자열을 StringBuilder에 누적해서 추가하고, 출력한 뒤 StringBuilder를 비워주는 역할을 합니다. 이렇게 함으로써 다음 테스트 케이스의 결과가 현재 테스트 케이스의 결과와 혼동되지 않게 됩니다.
2. 메모리 관리 및 성능 향상: StringBuilder 객체는 내부적으로 버퍼를 사용하여 문자열을 처리합니다. delete() 메서드를 사용하여 이전 테스트 케이스의 결과를 삭제함으로써 버퍼 내의 데이터를 지우고 재활용할 수 있습니다. 이로써 메모리 관리 및 성능 향상을 이룰 수 있습니다.
즉, sb.delete(0, sb.length());은 이전 테스트 케이스의 결과를 제거하고 StringBuilder 객체를 초기화하는 역할을 합니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
int testCase = Integer.parseInt(br.readLine());
for (int i = 0; i < testCase; i++) {
String[] input = br.readLine().split(" ");
int repeat = Integer.parseInt(input[0]);
char[] chars = input[1].toCharArray();
for (int j = 0; j < chars.length; j++) {
for (int k = 0; k < repeat; k++) {
sb.append(chars[j]);
}
}
System.out.println(sb);
sb.delete(0, sb.length());
}
}
}
메모리 | 시간 | 언어 | 코드 길이 |
12728KB | 68ms | Java8 | 705B |
참고 링크 :
https://devaily.tistory.com/11
https://code0xff.tistory.com/10
https://developer-talk.tistory.com/689
https://codechacha.com/ko/java-stringbuilder-clear/
'알고리즘 > 백준' 카테고리의 다른 글
[백준/BOJ][Java][11718] 그대로 출력하기 (0) | 2023.08.25 |
---|---|
[백준/BOJ][Java][1152] 단어의 개수 (0) | 2023.08.24 |
[백준/BOJ][Java][2908] 상수 (0) | 2023.08.24 |
[백준/BOJ][Java][10809] 알파벳 찾기 (1) | 2023.08.24 |
[백준/BOJ][Java][9086]문자열 (0) | 2023.08.24 |