[Java] 백준 5430번 : AC

세 진·2023년 7월 22일
0

알고

목록 보기
2/4

문제

해결 방법

시간 제한이 꽤 빡빡하기 때문에 배열을 진짜 역순 정렬하고, index를 삭제하기에는 무조건 시간 초과가 날 것 같았다
물론 좋은 자료구조형을 쓰게 되면 어느정도 줄일 수는 있었겠지만 ?
나는 그래서 원래 배열은 가만히 두고, 배열의 상태를 저장할 수 있는 3가지의 변수를 이용하였다

  1. isReverse - R 명령어로 인해 방향이 계속 바뀌는데, 정방향인지 역방향인지를 저장하는 변수 : Boolean
  2. leftIndex - D 명령어로 인해 처음 수를 버리는데, 왼쪽 시작 index를 저장하는 변수 : int
  3. rightIndex - 마찬가지로 역순일 때 처음 수를 버릴때에는 오른쪽 끝 index를 저장하는 변수 : int

이거만 보면 별로 안 어려워 보이지 ? 근데 5번 틀림

주의사항

일단 배열의 범위를 내가 조작하기 때문에 error 조건에 대한 핸들링을 신경써야 한다.
그리고, 극악의 String parsing을 보여준다 ("[1,2,3,4]" 이렇게 입력을 준다 ...)
1. leftIndex와 rightIndex가 같아지는 시점에, 즉 배열의 크기가 0일 때 남은 명령어가 없거나 R만 남아있어야 한다.
2. String을 int타입으로 바꾸는 과정에서 각종 Exception을 주의해야 한다.

난 백준 다 좋은데 경계값 예외처리로 장난 좀 안 쳤으면 좋겠다 ㅎㅎ

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

/**
 * <pre>
 * 백준 5430. AC
 * 시간초과에 유의하기 위해 reverse, delete를 배열에 직접 구현하는 것이 아닌, 범위를 설정하고 방향을 설정하는 변수로 저장
 * 명령어에 따라 해당 변수들을 조작하며 최종 정답을 구하였음.
 * </pre>
 * @author 세진
 *
 */
public class Main {

	public static void main(String[] args) throws NumberFormatException, IOException {

		// user input을 위한 BufferedReader 객체 생성
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		// 테스트케이스 수 t 입력받아 Integer로 parse
		int t = Integer.parseInt(br.readLine());
		
		// 입력받은 t만큼 반복
		// 현재 test case에서 예외 발생 시 바로 다음 case로 넘어갈 수 있게 조치하기 위한 nextCase 레이블 부여
		nextCase:
		for (int test_case = 1; test_case <= t; test_case++) {
			
			// 배열조작 명령어 commands 배열에, input 배열 길이 n에 입력받음
			char[] commands = br.readLine().toCharArray();
			int n = Integer.parseInt(br.readLine());
			
			// case 1) input배열 크기가 0일 때 (이 경우에는 더 이상 요소를 지울 수 없음)
			if (n == 0) {
				
				// 0이기 때문에 무조건 입력 "[]" 으로 주어지기 때문에 readLine으로 저장할 필요 없는 입력 날리기
				br.readLine();
				
				// commands 배열을 돌면서 반복
				for (int i = 0; i < commands.length; i++) {
					
					// D (삭제) 명령어가 나오면 error 출력하고 다음 case로 넘어감
					if (commands[i] == 'D') {
						System.out.println("error");
						continue nextCase;
					}
				}
				
				// D 명령어 없이 R (reverse) 명령어만 나오게 된다면 빈 배열 그대로 출력 후 다음 case로 넘어감
				System.out.println("[]");
				continue nextCase;
			}
			
			// case 2) input 배열 크기가 0이 아닐 때
			// 배열 입력받기 위한 arr 배열 선언
			int[] arr = new int[n];
			
			// 배열 입력 string을 inputStr에 입력받고, 뒤에 '[', ']' 을 떼어내고 "," 기준으로 split
			String inputStr = br.readLine();
			String arrStr = new String(Arrays.copyOfRange(inputStr.toCharArray(), 1, inputStr.length() - 1));
			String[] arrStrSplit = arrStr.split(",");
			
			// split 결과 값 하나씩 Integer로 parse 후 arr에 저장
			for (int i = 0; i < n; i++) {
				
				arr[i] = Integer.parseInt(arrStrSplit[i]);
				
			}
			
			// isReverse : 역순인지 아닌지 저장하는 boolean 변수
			// leftStart : 왼쪽 인덱스 시작점을 저장할 정수형 변수 (정방향일때 D명령어가 들어오면 하나씩 늘려 범위를 축소한다)
			// rightStart : 오른쪽 인덱스 시작점을 저장할 정수형 변수 (역방향일때 D명령어가 들어오면 하나씩 줄여 범위를 축소한다)
			boolean isReverse = false;
			int leftStart = 0;
			int rightStart = n;
			
			// commands 배열의 크기만큼 반복
			for (int i = 0; i < commands.length; i++) {
				 
				if (commands[i] == 'R') { // R 명령어이면, isReverse를 현재 값의 반대값으로 바꿈
					isReverse = !isReverse;
					continue;
				}
				else if (commands[i] == 'D') { // D 명령어이면, isReverse의 방향에 따라 처리
					
					if (isReverse) { // 역순이면 rightStart를 1 감소
						rightStart--;
					}
					else { // 정방향이면 leftStart를 1 증가
						leftStart++;
					}
					
					// D명령어로 인해 범위가 줄어들다가 같아지는 시점이 오게 되면
					if (leftStart == rightStart) {
						
						// 마지막 명령어이면 빈 배열 출력 후 다음 case로 넘어감
						if (i == commands.length - 1) {
							System.out.println("[]");
							continue nextCase;
						}
						
						// 마지막 명령어가 아니면 남은 명령어들 중 D가 있는지 확인하기 위해 반복
						for (int j = i; j < commands.length; j++) {
							
							// D 있으면 오류이기 때문에 error 출력 후 다음 case로 넘어감
							if (commands[j] == 'D') {
								System.out.println("error");
								continue nextCase;
							}
						}
						
						// D가 없고 R만 있으면 빈 배열 출력 후 다음 case로 넘어감
						System.out.println("[]");
						continue nextCase;
						
					}
					
				}
				
			}
			
			// 확인하기 위한 출력구문
//			System.out.printf("left : %d, right : %d, isReverse : %b\n", leftStart, rightStart, isReverse);
			
			// 반복문 종료 후 출력 String을 만들기 위한 StringBuilder 객체 생성
			StringBuilder sb = new StringBuilder();
			sb.append("[");
			
			// 만약 남아있는 index가 1개라면 하나의 요소만 딱 추가해 괄호 닫아서 출력하고 다음 case로 넘어감
			if (leftStart == rightStart - 1) {
				sb.append(arr[leftStart]);
				sb.append("]");
				System.out.println(sb.toString());
				continue nextCase;
			}
			
			// 만약 정방향이라면 (역방향이 아니라면)
			if (!isReverse) {
				
				// left부터 right까지의 index들을 추가
				for (int i = leftStart; i < rightStart; i++) {
					sb.append(arr[i]);
					
					if (i != rightStart - 1) {
						sb.append(",");
					}
					else {
						sb.append("]");
					}
				}
				
			}
			else { // 역방향이면
				// right부터 left까지의 index들을 추가
				for (int i = rightStart - 1; i >= leftStart; i--) {
					sb.append(arr[i]);
					
					if (i != leftStart) {
						sb.append(",");
					}
					else {
						sb.append("]");
					}
				}
				
			}
			
			// 답 출력
			System.out.println(sb.toString());
			
			
			
		}
		
	}
	

}

느낀 점

일단 어거지로 풀긴 풀었는데 .. 내 코드를 다른 사람이 이해하기 쉽게 짜는 것 같진 않다
중복되는 코드들도 생각보다 많은 것 같고 해서 ,, 연습이 좀 더 필요할 듯

profile
비형따고싶다 ,,

0개의 댓글