코드: https://github.com/kgh128/Problem-Solving/blob/main/src/Baekjoon/p5430.java
수행할 함수들을 먼저 입력받는다. 모든 함수는 하나의 문자이므로 일단 수행 함수들을 String으로 입력받고, 나중에 함수를 수행할 때 한 문자씩 쪼개서 무슨 함수인지 판단한다.
String functions = br.readLine();
처음에는
split("")으로 파싱했는데. 어차피 하나의 문자가 하나의 함수인 것이 보장되어있으므로split("")으로 파싱하는 것이 별로 의미가 없다고 판단했다.split()을 쓰면 위의 코드보다 시간도 더 걸려서 위의 코드처럼 수정했다.
배열에 들어있는 수의 개수를 입력받는다.
int arraySize = Integer.parseInt(br.readLine());
배열을 일단 원본 그대로 입력받는다.(inputs) 배열이 []로 감싸져 있으므로 substring(startIndex, endIndex+1)을 써서 [] 안에 있는 내용물만 뽑아낸다. 그리고 그 뽑아낸 내용물을 split(",")을 써서 파싱하여 배열의 숫자 하나를 array 배열의 원소 하나로 넣는다.
String inputs = br.readLine();
String[] array = inputs.substring(1, inputs.length()-1).split(",");
StringTokenizer st = new StringTokenizer(br.readLine(), "[],");이렇게 한 번에 대괄호와 쉼표를 파싱해도 된다.
R 함수 때문에 배열을 뒤집어야 하는데, 실제로 배열을 뒤집는 것은 비효율적이다.
D 수행: 배열의 가장 앞에 있는 원소 삭제D 수행: 배열의 가장 뒤에 있는 원소 삭제이런 형식으로 동작하게 하여 배열을 뒤집은 효과를 주려고 하였다. 그러기 위해서 양방향으로 데이터를 입출력 할 수 있는 덱(Deque)을 사용하였다.
덱에 초기 배열을 입력한다. 만약 초기 배열이 빈 배열이면 array에 있는 첫번째 원소가 ""이다. Integer.parseInt("")는 수행할 수 없으므로 예외가 발생한다. 그래서 빈 배열이 아닐 때만 array의 원소를 정수로 바꿔서 덱에 넣도록 하였다.
Deque<Integer> deque = new ArrayDeque<>(arraySize);
if (arraySize > 0) {
for (String num: array) {
deque.add(Integer.parseInt(num));
}
}
초기 배열이 빈 배열인 경우를 고려하지 않아서 위에 설명한 것처럼 예외가 발생하였다.
현재 deque를 역방향으로 사용하고 있는지를 저장하는 변수인 isReverseDeque를 이용하였다.
isReverseDeque = false;isReverseDeque = true;함수들을 저장하고 있는 functions 문자열을 char형 배열로 바꿔서 각 문자(함수)를 돌면서 수행하였다.
R 수행: isReverseDeque의 값을 반대로 바꾼다. (true이면 false로, false이면 true로)D 수행: 배열의 가장 앞에 있는 원소 삭제 (removeFirst())D 수행: 배열의 가장 뒤에 있는 원소 삭제 (removeLast())Deque에서 덱이 비어있을 때 remove 계열 메소드를 사용하면 예외가 발생한다. 이를 이용하여 배열이 비어있을 때 D를 사용한 경우를 처리하였다. 함수를 수행하는 for문 자체를 try 블록 안에 넣고, 그 안에서 예외가 발생하면 에러가 난 경우이므로 catch 블록에서 출력 버퍼에 "error"를 저장하고, 현재 테스트 케이스를 탈출하였다.
boolean isReverseDeque = false;
try {
for (char func : functions.toCharArray()) {
if (func == 'R') {
isReverseDeque = !isReverseDeque;
}
else if (func == 'D' && !isReverseDeque) {
deque.removeFirst();
}
else {
deque.removeLast();
}
}
} catch (Exception e) {
bw.append("error\n");
continue;
}
최종 결과 배열도 처음에 입력받은 배열 형식으로 출력해야 한다. 그래서 일단 출력 버퍼에 [를 추가하였다. 그리고 덱에 있는 최종 결과 배열을 for문을 돌면서 출력 버퍼에 저장하였다.
bw.append("[");
int dequeSize = deque.size();
if (!isReverseDeque) {
for (int j = 0; j < dequeSize; j++) {
bw.append(deque.removeFirst()).append(',');
}
}
else {
for (int j = 0; j < dequeSize; j++) {
bw.append(deque.removeLast()).append(',');
}
}
처음에는
for문종료 조건에 바로deque.size()를 넣었다. 이러면 반복문 돌면서 원소가 하나씩 줄어들기 때문에, 현재 덱의 크기인deque.size()도 반복문을 돌면서 하나씩 줄어들었다. 그래서 생각했던 것 만큼 반복문을 돌지 않고 끝나서 결과가 제대로 출력되지 않았다.그래서 최종 결과 배열이 다 들어있을 때 덱의 크기를
dequeSize에 저장해놓고, 그 변수를for문의 종료 조건으로 사용하였다.
반복문을 돌 때 배열의 숫자와 함께 쉼표도 출력 버퍼에 저장하기 때문에 마지막 숫자 뒤에도 쉼표가 있다. 이 쉼표는 제거해줘야 하므로 deleteCharAt()을 이용하였다. 최종 결과 배열이 빈 배열이면 반복문을 안돌아서 출력 버퍼에 쉼표가 없다. 그러므로 이 경우는 제외하고 쉼표 제거를 해줘야 한다.
마지막으로 출력 버퍼에 ]를 추가하였다.
if (dequeSize > 0) {
bw.deleteCharAt(bw.length() - 1);
}
bw.append("]\n");
최종 결과 배열이 빈 배열인 경우를 고려하지 않고 쉼표 제거를 했다가
[가 제거되고 결과로]만 나온 케이스도 있었다. 그래서dequeSize가 0보다 큰 경우만 쉼표 제거를 하도록 수정하였다.처음에는 초기 배열 크기인
arraySize가 0보다 큰 경우에 쉼표 제거를 하도록 했는데, 이러면 초기 배열은 빈 배열이 아닌데D를 계속 수행해서 결과 배열이 빈 배열이 되는 경우를 걸러주지 못했다. 그래서 결과 배열의 크기인dequeSize를 이용하였다.