JAVA) 9093번 스택(Stack 클래스) 사용해서 단어 뒤집기, BufferedReader/Writer와 StringTokenizer 사용, 시간초과와 메모리초과 극복
import java.io.*;
import java.util.Stack;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
Stack<String> stack = new Stack();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter((System.out)));
String stringCnt = br.readLine();
int cnt = Integer.parseInt(stringCnt);
for(int i=0;i<cnt;i++) {
String temp = br.readLine();
// String[] wordArray = temp.split(" ");
StringTokenizer st = new StringTokenizer(temp); // temp 문자열을 공백을 기준으로 토큰으로 나누어 순서대로 호출할 수 있게 해줌
while (st.hasMoreTokens()) { // 문장의 모든 단어 iterate
String word = st.nextToken(); // 단어 하나 불러오기
for (int j=0;j<word.length();j++) {
stack.push(word.substring(j, j+1)); // 단어 알파벳으로 슬라이싱하고 push
}
while (!stack.empty()) {
bw.write(stack.pop()); // stack에 넣어진 단어 1개에 대한 모든 알파벳 pop
}
bw.write(" "); // 단어 간 띄어쓰기
}
bw.write("\n"); // 다음 문장으로 가기 위한 개행
bw.flush(); // 작성된(남아있는) 버퍼 콘솔에 출력하기
}
bw.close(); // 버퍼 닫기
}
}
자바 라이브러리에서 제공하는 Stack 클래스를 사용했다.
Stack<자료형> 스택변수이름 = new Stack(); 으로 선언한다.
Stack 클래스가 지원하는 핵심 메소드는
- pop() : 스택의 top(맨 위 object)를 제거하고 그것을 반환
- push(item) : item을 스택의 top에 저장
- peek() : 스택의 top object를 반환(제거하지 않음)
- empty() : 스택이 비어있으면 true, 비어있지 않으면 false를 반환
처음에는 split를 2회 사용하고 입출력에 Scanner 클래스를 사용하였다.
문제에서 요구하는 기능은 정상적으로 수행하였지만 메모리 초과와 시간 초과 판정이 나왔다.
아래 코드는 처음 메모리 초과 판정을 받은 코드이다.
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
int cnt;
Stack<String> stack = new Stack();
Scanner sc = new Scanner(System.in);
cnt = sc.nextInt();
sc.nextLine(); // 위 cnt = sc.nextInt();에서는 개행을 제외한 정수 값만 입력받기 때문에, 개행을 처리해 주어야 테스트 문장을 제대로 입력 받을 수 있음(처리 안하면 nextLine()이 \n을 입력으로 받아옴)
for(int i=0;i<cnt;i++) {
String temp = sc.nextLine();
String[] wordArray = temp.split(" ");
for (int j=0;j<wordArray.length;j++){
String[] alphabetArray = wordArray[j].split("");
String reversedWord = "";
for (int k=0;k<alphabetArray.length;k++){
stack.push(alphabetArray[k]);
}
for (int k=0;k<alphabetArray.length;k++){
reversedWord += stack.pop();
}
System.out.print(reversedWord + " ");
}
System.out.println();
}
}
}
메모리 소비를 줄이기 위해 배열 사용을 줄였다.
이에 슬라이싱 결과를 배열로 반환하는 split() 대신, 결과를 String형으로 반환하는 substring() 메소드를 사용했다.
그리고 문장의 각 단어들을 반아오기 위해서는 Stringtokenizer를 사용했다.
시간을 줄이기 위해 입출력에 상대적으로 많은 시간이 소요되는 Scanner 대신 BufferedReader/Writer 클래스를 사용했다. (입력은 적지만 출력이 많은 경우에는 StringBuilder를 사용해서 한 문자열로 만들어 한번에 출력하는 방법을 사용할 수도 있다)
각 클래스의 object 생성 방법은 이러하며, IO Exeption의 처리가 요구된다. (클래스에 throws IOException)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter((System.out)));
BufferedReader의 경우에 bw.readLine()을 통해 개행 기준 한 줄을 읽어올 수 있다.
BefferedWriter의 경우에 bw.write("출력할 문자")를 통해 출력할 내용을 버퍼에 담을 수 있고
(참고로 bw.write()에는 자동 개행 기능이 없다.)
bw.flush()를 통해 버퍼에 담긴 내용을 콘솔에 출력할 수 있다.
모든 출력이 끝난 후에 bw.flush()와 bw.close()를 호출해서 버퍼를 비우고 닫아줘야한다.