[백준] 5430 : AC - JAVA

Benjamin·2023년 9월 14일
0

BAEKJOON

목록 보기
69/70

Troubleshooting

import java.util.*;
import java.io.*;

public class Main {
	static String[] arr;
	static Queue<Character> q = new LinkedList<>();
	static Queue<Character> answer = new LinkedList<>();
	static int start, end;
	static int isReverse;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		StringBuilder sb = null;
		
		for(int i=0; i<T; i++) {
			sb = new StringBuilder();
			isReverse = -1;
			start = 0;
			q.clear();
			String p = br.readLine();
			for(int j=0; j<p.length(); j++) {
				q.add(p.charAt(j));
				
			}
			int n = Integer.parseInt(br.readLine());
			end = n-1;
			arr = new String[n];
			String temp = br.readLine();
			arr = temp.substring(1, temp.length()-1).replace(",", " ").split(" ");
			
			readFunction();
			if(isNone()) {
				sb.append("error");
			} else {
				sb.append("[");
				if(isReverse == 1) {
					for(int k = start ; k>=end; k--) {
						sb.append(arr[k] + ",");
					}
				} else {
					for(int k = start ; k<=end; k++) {
						sb.append(arr[k] + ",");
					}
				}
				sb.deleteCharAt(sb.length()-1);
				sb.append("]");
			}
			System.out.println(sb);
		}
	}
	
	public static void readFunction() {
		while(!q.isEmpty()) {
			char cmd = q.poll();
			
			switch(cmd) {
				case 'R' : 
					reverseIdx();
					break;
				case 'D' : 
					deleteIdx();
					break;	
			}
		}
	}
	
	public static void reverseIdx() {
		int temp = start;
		start = end;
		end = temp;
		isReverse *= (-1);
	}
	
	public static void deleteIdx() {
		if(isReverse == 1) {
			start--;
		} else if(isReverse == -1) {
			start++;
		}
	}
	
	public static boolean isNone() {
		boolean answer= false;
		if(isReverse == 1) {
			if(start < end) {
				answer=  true;
			}
		}
		if(isReverse == -1) {
			if(start > end) answer = true;
		}
		return answer;
	}
}

문제

테스트 케이스는 맞았는데, 틀렸습니다를 받았다.

원인

1
D
1
4

를 넣으니, ]만 출력됐다.
isNone()이 true로 동작해서 error를 출력했다는말이다.

근데 문제를 다시 살펴보니,, 조건을 헷갈렸다.

값이 비었을 때 (isNone == ture) error를 출력하는게 아니라, 값이 비었는데 D를 수행하면 그때 출력하라는 것이다.

따라서 D를 수행할 때, 값이 비어있으면 에러 출력으로 연결될 수 있게 플래그 변수를 하나 사용했다.

해결

readFunction() 에서 case 'D'에 아래 코드를 추가했다.

if(isNone()) isError = true;

+수정한 후 주어진 테스트 케이스로 돌려보니 세번째의 값이 error로 출력됐다.
테스트케이스식으로 작동하는 코드에서 어떤 변수를 사용한다면, 꼭 각 테케가 돌아갈 때 마다 해당 변수를 초기화시켜주는것을 잊지말자!! (isError=false 초기화)

제출 코드

import java.util.*;
import java.io.*;

public class Main {
	
	static String[] arr;
	static Queue<Character> q = new LinkedList<>();
	static Queue<Character> answer = new LinkedList<>();
	static int start, end;
	static int isReverse;
	static boolean isError = false;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int T = Integer.parseInt(br.readLine());
		StringBuilder sb = null;
		
		for(int i=0; i<T; i++) {
			sb = new StringBuilder();
			isReverse = -1;
			start = 0;
			isError = false;
			q.clear();
			String p = br.readLine();
			for(int j=0; j<p.length(); j++) {
				q.add(p.charAt(j));
				
			}
			int n = Integer.parseInt(br.readLine());
			end = n-1;
			arr = new String[n];
			String temp = br.readLine();
			arr = temp.substring(1, temp.length()-1).replace(",", " ").split(" ");
			
			readFunction();
			if(isError) {
				sb.append("error");
			} else {
				sb.append("[");
				if(isReverse == 1) {
					for(int k = start ; k>=end; k--) {
						sb.append(arr[k] + ",");
					}
				} else {
					for(int k = start ; k<=end; k++) {
						sb.append(arr[k] + ",");
					}
				}
				if(sb.length()>1)sb.deleteCharAt(sb.length()-1);
				sb.append("]");
			}
			System.out.println(sb);
		}
	}
	
	public static void readFunction() {
		while(!q.isEmpty()) {
			char cmd = q.poll();
			
			switch(cmd) {
				case 'R' : 
					reverseIdx();
					break;
				case 'D' : 
					if(isNone()) isError = true;
					deleteIdx();
					break;	
			}
		}
	}
	
	public static void reverseIdx() {
		int temp = start;
		start = end;
		end = temp;
		isReverse *= (-1);
	}
	
	public static void deleteIdx() {
		if(isReverse == 1) {
			start--;
		} else if(isReverse == -1) {
			start++;
		}
	}
	
	public static boolean isNone() {
		boolean answer= false;
		if(isReverse == 1) {
			if(start < end) {
				answer=  true;
			}
		}
		if(isReverse == -1) {
			if(start > end) answer = true;
		}
		return answer;
	}
}

주의할 점

  • 문제의 조건을 놓치지말고 꼭 잘 챙기자! 사소한것도
    +조건의 선후관계까지!!
  • 변수의 초기화가 필요하지는 않은지 잘 챙기자

공부할 풀이

보통 풀이를 찾아보니, 배열을 사용하려다가 시간초과를 접했다고한다.
(그런 사람들 풀이를 보니 배열을 뒤집을 때 진짜 뒤집은 배열을 다른 배열에다가 저장하고있음..)
근데, 난 데이터가 너무많아서 그건 너무 비효율적이라고 생각했기때문에, 뒤집는거나 삭제하는거나 인덱스를 사용해서 풀었다.
따라서 배열을 사용하더라도 시간초과가 나지는 않았다.

근데, 더 찾아보니 시간초과때문에 배열이 아닌 Deque를 사용하더라.
Queue는 사용해도 Deque 자료구조를 많이 사용하지 않았었던 나기에 이 풀이를 공부한다.

import java.io.*;
import java.util.*;

public class Main {
	static ArrayDeque<Integer> deque;
	static StringBuilder sb = new StringBuilder();

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		int T = Integer.parseInt(br.readLine());
		while(T --> 0) {

			String p = br.readLine();
			int number = Integer.parseInt(br.readLine());

			StringTokenizer st = new StringTokenizer(br.readLine(),"[],");
			deque = new ArrayDeque<Integer>();

			for(int i=0; i<number; i++) {
				deque.add(Integer.parseInt(st.nextToken()));
			}

			AC(p);
		}

		System.out.println(sb);
	} // End of main

	static void AC(String p) {
		boolean forward_direction = true;

		for(char function : p.toCharArray()) {

			if(function == 'R') {
				forward_direction = !forward_direction;
				continue;
			}

			// 정방향일 때
			if( forward_direction ) {

				// 덱이 비었으면,
				if(deque.pollFirst() == null) {
					sb.append("error\n");
					return;
				}
			}
			// 역방향 일때 forward_direction = true
			else {

				if(deque.pollLast() == null) {
					sb.append("error\n");
					return;
				}
			}
		}

		makePrintString(forward_direction);
	}

	private static void makePrintString(boolean forward_direction) {

		sb.append('[');

		if(deque.size() > 0) {
			if(forward_direction) {
				sb.append(deque.pollFirst());

				while(!deque.isEmpty()) {
					sb.append(',').append(deque.pollFirst());
				}
			}
			else {
				sb.append(deque.pollLast());

				while(!deque.isEmpty()) {
					sb.append(',').append(deque.pollLast());
				}
			}
		}

		sb.append(']').append('\n');
	} // End of makePrintString
} // End of class

설명

  1. 테스트케이스를 [,]를 기준으로 토큰처리해서 숫자로 만들어서 deque에 넣어줍니다.
			StringTokenizer st = new StringTokenizer(br.readLine(),"[],");
			deque = new ArrayDeque<Integer>();

			for(int i=0; i<number; i++) {
				deque.add(Integer.parseInt(st.nextToken()));
			}
            
  1. R일 경우 forward_direction를 역으로 바꿔줍니다.
			if(function == 'R') {
				forward_direction = !forward_direction;
				continue;
			}

-> boolean 타입의 변수를 특정 상황에 계속 체인지시켜주려면 !연산자를 사용하면된다

  1. 그리고 forward_direction이 true일때는 정방향이므로 가장 먼저 한 줄을 출력하고 난 뒤
    ','가 붙을지 안붙을지 판단하기 위해서 deque.isEmpty()를 판별합니다
    만약 deque이 비어있지 않다면, ','를 사이에 두고 앞에서 부터 계속 원소를 꺼냅니다.

역방향도 deque.pollLast()만 다르고 과정은 같습니다.

			if(forward_direction) {
				sb.append(deque.pollFirst());

				while(!deque.isEmpty()) {
					sb.append(',').append(deque.pollFirst());
				}
			}
            else {
				sb.append(deque.pollLast());

				while(!deque.isEmpty()) {
					sb.append(',').append(deque.pollLast());
				}
			}

공부한 사항

  • public StringTokenizer(String str,String delim); : 특정 delim으로 문자열을 분리합니다.

참고
https://velog.io/@lifeisbeautiful/Java-%EB%B0%B1%EC%A4%80-5430%EB%B2%88-AC-%EC%9E%90%EB%B0%94

0개의 댓글