자료구조/문제풀이

[백준 JAVA] 1406 에디터

휴먼코딩 2024. 7. 12. 22:24

1406 에디터

https://www.acmicpc.net/problem/1406

 

문제설명

stack을 사용해서 데이터 순서에 따라 삽입 및 삭제

접근방식

O(n + m) 선형 시간복잡도

    • L 명령어 (왼쪽으로 커서 이동): leftSt에서 pop하고 rightSt로 push → O(1)
    • D 명령어 (오른쪽으로 커서 이동): rightSt에서 pop하고 leftSt로 push → O(1)
    • B 명령어 (커서 왼쪽 문자 삭제): leftSt에서 pop → O(1)
    • P 명령어 (문자 추가): leftSt에 push → O(1)
  1. 문자열 출력: leftSt에 남아있는 문자들을 모두 rightSt로 옮기고, rightSt를 순회하며 출력 → O(N)

따라서 전체 시간 복잡도는 초기 문자열의 길이 N과 명령어 개수 M에 따라 결정된다.

명령어는 O(1) 시간복잡도로 처리되며, 문자열 출력 처리가 O(N) 시간이 걸린다.

총 시간 복잡도는 O(N + M)이다.


문제 조건 분석 과정

 

스택 활용: 왼쪽 스택과 오른쪽 스택을 사용하여 커서의 위치를 기준으로 문자열을 관리한다.

결과 출력: 마지막에 rightSt를 역순으로 꺼내어 StringBuilder에 추가하고, 최종적으로 결과 문자열을 출력한

자료구조

Stack (Stack<Character> leftSt, rightSt)

  • leftSt: 왼쪽 스택으로, 초기 문자열을 문자 단위로 역순으로 저장한다.
  • 커서를 기준으로 왼쪽에 있는 문자들을 관리한다.
  •  
  • rightSt: 오른쪽 스택으로, 왼쪽 스택에서 pop된 문자들을 순서대로 저장한다.
  • 커서를 기준으로 오른쪽에 있는 문자들을 관리한다.

틀린이유

문제를 이해 못해서 백준 문제를 다시 읽어보는데에만 시간이 오래 소요되었다.

문제를 보는 연습 필요

올바른 접근 방식 및 해결 방식

각 명령어 처리 시 스택이 비어 있는지 확인하기

처음엔 linkedlist를 사용했다가 시간 초과가 나버렸다.

stack은 연산이 o(1)의 상수 시간을 가지기 때문에  시간 초과를 방지할 수 있음

전체코드

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

public class Main_1406에디터 {

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

        String str = br.readLine(); //초기 문자열
        int M = Integer.parseInt(br.readLine()); //명령어 개수

        Stack<Character> leftSt = new Stack<>(); //왼쪽 스택 (커서 기준 왼쪽 문자열)
        Stack<Character> rightSt = new Stack<>(); //오른쪽 스택 (커서 기준 오른쪽 문자열)

        for(char c : str.toCharArray()) {
            leftSt.push(c); //문자열을 문자 단위로 왼쪽 스택에 넣음
        }

        for(int i = 0; i < M; i++) {
            String command = br.readLine(); //명령어 한 줄을 읽어온다
            char c = command.charAt(0); //명령어의 첫 번째 문자를 가져온다

            switch(c) {
                case 'L': //왼쪽으로 커서 이동
                    if(!leftSt.isEmpty())
                        rightSt.push(leftSt.pop()); //왼쪽에서 오른쪽으로 이동
                    break;
                case 'D': //오른쪽으로 커서 이동
                    if(!rightSt.isEmpty())
                        leftSt.push(rightSt.pop()); //오른쪽에서 왼쪽으로 이동
                    break;
                case 'B': //커서 왼쪽 문자 삭제
                    if(!leftSt.isEmpty()) {
                        leftSt.pop(); //왼쪽 스택에서 문자 삭제
                    }
                    break;
                case 'P': //문자 추가
                    char t = command.charAt(2); //명령어에서 추가할 문자 가져오기
                    leftSt.push(t); //왼쪽 스택에 추가
                    break;
                default:
                    break;
            }
        }

        while(!leftSt.isEmpty()) {
            rightSt.push(leftSt.pop()); //남아있는 모든 문자를 오른쪽 스택으로 옮긴다
        }

        StringBuilder result = new StringBuilder();
        while(!rightSt.isEmpty()) {
            result.append(rightSt.pop()); //오른쪽 스택에서 문자를 꺼내어 결과에 추가
        }
        System.out.println(result.toString());
    }
}