[백준] 5430 AC - 문자열, 구현

jckim22·2023년 8월 11일
0

[ALGORITHM] STUDY (PS)

목록 보기
73/86

난이도

Gold 5

풀이 참고 유무

x

막힌 부분

x

문제

문제 바로가기
선영이는 주말에 할 일이 없어서 새로운 언어 AC를 만들었다. AC는 정수 배열에 연산을 하기 위해 만든 언어이다. 이 언어에는 두 가지 함수 R(뒤집기)과 D(버리기)가 있다.

함수 R은 배열에 있는 수의 순서를 뒤집는 함수이고, D는 첫 번째 수를 버리는 함수이다. 배열이 비어있는데 D를 사용한 경우에는 에러가 발생한다.

함수는 조합해서 한 번에 사용할 수 있다. 예를 들어, "AB"는 A를 수행한 다음에 바로 이어서 B를 수행하는 함수이다. 예를 들어, "RDD"는 배열을 뒤집은 다음 처음 두 수를 버리는 함수이다.

배열의 초기값과 수행할 함수가 주어졌을 때, 최종 결과를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. T는 최대 100이다.
각 테스트 케이스의 첫째 줄에는 수행할 함수 p가 주어진다. p의 길이는 1보다 크거나 같고, 100,000보다 작거나 같다.
다음 줄에는 배열에 들어있는 수의 개수 n이 주어진다. (0 ≤ n ≤ 100,000)
다음 줄에는 [x1,...,xn]과 같은 형태로 배열에 들어있는 정수가 주어진다. (1 ≤ xi ≤ 100)
전체 테스트 케이스에 주어지는 p의 길이의 합과 n의 합은 70만을 넘지 않는다.

출력

각 테스트 케이스에 대해서, 입력으로 주어진 정수 배열에 함수를 수행한 결과를 출력한다. 만약, 에러가 발생한 경우에는 error를 출력한다.

예제 입력

4
RDD
4
[1,2,3,4]
DD
1
[42]
RRD
6
[1,1,2,3,5,8]
D
0
[]

예제 출력

[2,1]
error
[1,2,3,5,8]
error

문제 검토

로직은 매우 간단해보이지만, Gold 5인 이유가 있을 것이다.
아마도 reverse를 하게 되는 과정에서 시간초과가 나게 되는 경우일 것이다.
데이터 셋이 많아서 최대한 O(n)으로 풀어보자.

풀이(python)

Python

from collections import deque
from sys import stdin
input=stdin.readline
t=int(input())
#O(100)
for _ in range(t):
    mode=True
    check=True
    func=input().strip()
    n=int(input())
    arr=input().strip()
    arr=arr.replace('[','')
    arr=arr.replace(']','')
    if arr:
        arr=deque(list(map(int,arr.split(','))))
    #O(n)
    elif not arr and 'D' not in func:
        print('[]')
        continue
    else:
        print('error')
        continue
    #O(n)
    for x in func:
        if x == 'R':
            mode=not mode
        elif x == 'D':            
            if mode:
                if arr:
                    arr.popleft()                
                else:
                    check=False
                    print('error')
                    break
            else:
                if arr:
                    arr.pop()                
                else:
                    check=False
                    print('error')
                    break
    if not check:
        continue
    if not arr:
        print('[]')
        continue
    answer='['
    #O(n)
    if mode:
        for x in arr:
            answer+=str(x)+','
    else:
        for x in range(len(arr)-1,-1,-1):      
            answer+=str(arr[x])+','
    answer=answer[:-1]
    answer+=']'
    print(answer)

Java

import java.util.*;
import java.io.*;
public class Main{
    static ArrayDeque<Integer> q;
    static int t;
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        t=sc.nextInt();
        sc.nextLine();
        for(int i=0; i<t;i++){
            boolean mode=true;
            boolean check=true;
            boolean cc=false;
            String func=sc.next();
            sc.nextLine();
            int n=sc.nextInt();
            sc.nextLine();
            String arr=sc.next();
            sc.nextLine();
            //substring으로 양쪽의 대괄호를 잘라준다.
            arr=arr.substring(1,arr.length()-1);
            //함수중에서 'D'가 존재하면  cc를 true로 체크
            for(int j=0; j<func.length(); j++){
                if(func.charAt(j)=='D'){
                    cc=true;
                    break;
                }
            }
            //대괄호를 제거해도 남는게 있다면 숫자가 있는 것이므로
            if(!arr.isEmpty()){
                //숫자들을 ,기준으로 나눠주고
                String[] qs=arr.split(",");
                //q에 하나씩 String을 Integer.valueOf로 형변환하면서 삽입한다.
                q=new ArrayDeque<>();
                for(int j=0; j<qs.length;j++){
                    q.add(Integer.valueOf(qs[j]));
                }
            }
            //arr이 대괄호를 제거하니 비어있고 함수 중에 D가 없으면 답은 빈괄호일 것이므로 []를 반환
            else if(arr.isEmpty() && !cc){
                System.out.println("[]");
                continue;
            }
            //그것도 아니라면 arr이 비었는데 함수 D가 있을 것이므로 error 출력
            else{
                System.out.println("error");
                continue;
            }
            //함수의 길이만큼 반복함
            for(int j=0; j<func.length();j++){
                //mode에 따라서 왼쪽인지 오른쪽 pop인지 결정
                if (func.charAt(j) == 'R'){
                    mode=!mode;
                }
                else if(func.charAt(j)=='D'){
                    if (mode){
                        if (!q.isEmpty()){
                            q.pollFirst();
                        }
                        else{
                            check=false;
                            System.out.println("error");
                            break;
                        }
                    }
                    else{
                        if (!q.isEmpty()){
                            q.pollLast();
                        }
                        else{
                            check=false;
                            System.out.println("error");
                            break;
                        }
                    }
                }
            }
            if (!check){
                continue;
            }
            if(q.isEmpty()){
                System.out.println("[]");
                continue;
            }
            //답을 출력하기 위해 StringBuilder를 사용
            StringBuilder sb=new StringBuilder();
            sb.append("[");
            if(mode){
                while(!q.isEmpty()){
                    sb.append(q.pollFirst());
                    sb.append(",");
                }
            }
            else{
                while(!q.isEmpty()){
                    sb.append(q.pollLast());
                    sb.append(",");
                }
            }
            //마지막 쉼표 제거 후 닫는 대괄호를 append
            sb.deleteCharAt(sb.length()-1);
            sb.append("]");
            System.out.println(sb);
        }
    }
}

#아이디어
#R과 D, 두 개의 함수밖에 존재하지 않으므로 함수에 따라 MODE를 변경해서 왼쪽으로 pop할지 오른쪽에서 pop할지를 결정한다.
#만약 큐기 비면 error를 출력
#시간 복잡도
#reverse로 배열을 거꾸로 돌리지 않고 사용하는 건 pop 밖에 없으니 충분히 가능하다고 보임
#이중 for문이 하나도 없으므로 총 O(n)의 수행시간

걸린 시간

35:11 - 파이썬 풀이 기준

총평

운이 좋게도 deque를 사용하여 큐와 스택을 동시에 사용해 풀어낼 생각을 바로 할 수 있었다.
하지만 예외처리에서 시간이 오래걸렸다.
RR은 방향만 바꾸기 때문에 만약 숫자가 0개가 들어왔다면 error가 아니라 빈 괄호를 출력해야 했었다.

profile
개발/보안

0개의 댓글