백준 1874 스택 수열 [JAVA]

Ga0·2023년 6월 21일
0

baekjoon

목록 보기
73/125

문제 해석

  • 첫째 줄에는 입력받을 숫자의 개수(N)을 입력받고, N개 만큼 숫자를 입력받는데, 오름차순으로 입력받으면 해당 숫자만큼 요소를 차례대로 추가하고(이미 추가된 숫자(pop이 된 숫자)일 경우는 생략), 해당 숫자를 뺀다(pop). 내림차순일 경우는 그 숫자의 요소가 나올 때까지 꺼낸다(pop).
  • 문제 해석이 다소 복잡한데 아래의 설명의 흐름대로 코드를 작성하면 된다.
  • 이 예제의 답은 출력값의 +, - 하나 마다 줄바꿈을 해서 출력하면 된다. (사진에서는 직관적으로 설명하고자 단계별로 나온 출력값을 한번에 넣어준 것 이다.)

틀린 코드

import java.io.*;

public class Main {

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

        int N = Integer.parseInt(br.readLine()); //입력받을 숫자이면서 스택의 크기

        int[] stack = new int[N];

        int index = 0; //가장 마지막에 있는 요소의 인덱스
        int start = 0; //입력받은 숫자의 누적 크기(입력받은 가장 큰 숫자가 저장됨) => 오름차순 판정 여부

        // N 번 반복
        while(N -- > 0) {
            int value = Integer.parseInt(br.readLine()); //입력받은 숫자(하나)

            if(value > start) { // 입력받은 값이 가장 큰 숫자가 입력받은 값보다 클 경우 (오른차순 판별)
                // start + 1부터 입력받은 value 까지 push를 한다.
                for(int i = start + 1; i <= value; i++) { //value만큼 넣는다. 요소들을
                    stack[index] = i;
                    index++;
                    bw.append('+').append('\n');
                }

                start = value;     // 다음 push 할 때 오름차순인지 알 수 있도록 변수 초기화

            } else if(stack[index - 1] != value) { // top에 있는 원소가 입력받은 값과 같지 않은 경우
                System.out.println("NO"); //버퍼에 담으면 NO가 출력되지 않아서 println을 사용
                return;    // 찾을 수 없는 요소이므로 빠져나온다. (될 수 없는 스택 수열) => while문을 나온다.
            }

            index--;

            bw.append('-').append('\n'); // 오름차순의 경우 마지막 입력받은 요소는 넣자마자 빼야하므로 pop(-)
        }

        br.close();

        bw.flush();
        bw.close();
    }

}
  • 코드에 대한 설명은 주석으로 작성해 두었다.

틀린 결과

  • 하지만 이유를 모르겠는 틀림...

코드 (수정)

import java.io.*;

public class Main {

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

        int N = Integer.parseInt(br.readLine()); //입력받을 숫자이면서 스택의 크기

        int[] stack = new int[N];

        int index = 0; //가장 마지막에 있는 요소의 인덱스
        int start = 0; //입력받은 숫자의 누적 크기(입력받은 가장 큰 숫자가 저장됨) => 오름차순 판정 여부

        // N 번 반복
        while(N -- > 0) {
            int value = Integer.parseInt(br.readLine()); //입력받은 숫자(하나)

            if(value > start) { // 입력받은 값이 가장 큰 숫자가 입력받은 값보다 클 경우 (오른차순 판별)
                // start + 1부터 입력받은 value 까지 push를 한다.
                for(int i = start + 1; i <= value; i++) { //value만큼 넣는다. 요소들을
                    stack[index] = i;
                    index++;
                    sb.append('+').append('\n');
                }

                start = value;     // 다음 push 할 때 오름차순인지 알 수 있도록 변수 초기화

            } else if(stack[index - 1] != value) { // top에 있는 원소가 입력받은 값과 같지 않은 경우
                // 여기서 한번이라도 여기에 걸리면 여태까지 수행한 출력값도 무시하고 그냥 NO만 출력해야하므로
                // 버퍼를 쓰지 않고 println을 사용
                System.out.println("NO");
                System.exit(0);    // 찾을 수 없는 요소이므로 빠져나온다. (시스템 종료)
            }

            index--;

            sb.append('-').append('\n'); // 오름차순의 경우 마지막 입력받은 요소는 넣자마자 빼야하므로 pop(-)
        }

        br.close();

        System.out.println(sb);
    }

}
  • BufferedWriter대신 StringBuilder이 해결이 되었다. (다른 사람의 코드를 보니 StringBuilder을 쓰고 있었다.)

  • 콘솔에 출력되는 결과 값은 앞의 코드와 이쪽 코드가 같지만... 틀렸다해서 이유는 진짜 모르겠다.

추측!!

1. BufferedWriter

  • BufferedReader 와 BufferedWriter를 SET처럼 써왔는데 BufferedWriter의 한계점이 존재한다고 한다...
  • BufferedWriter 는 비동기적 버퍼 스트림인데, 비동기적 버퍼 스트림은 입력받은 데이터를 받다가 버퍼가 꽉차버리면 버퍼안에 있는 데이터를 자동적으로 비워버린다는 것이다.
  • flush() 함수 : 버퍼가 다차지 않았는데 출력을 하는 용도로 사용한다.
  • 즉, 틀린 코드를 수행하면서 입력값이 더 있는데, 버퍼가 차는 바람에 아마 중간에 비워버린 듯 하다. => 틀린 이유!!
    그렇다면, 해결방법으로는 뭐가 있을까? 그게 바로 StringBuider이다.
    2. StringBuider
  • StringBuider는 한마디로 변경가능한 문자열이다. (버퍼처럼 크기가 정해져 있지 X)
  • StringBuilder를 사용하면 비동기적으로 수행하는 것이 많을 때 StringBuilder() 함수를 이용하는게 안전하다. (중간에 비우는 일이 없기 때문!!)

결과

느낀 점

  • 개념 정리 좀 제대로 해야할 것 같다. (개념 정리 제대로 안된 상태에서 코드 작성하면 발생하는 문제점을 직면한 문제)

0개의 댓글