[ 백준 문제 10811 / 자바 ] 바구니 뒤집기

2023. 2. 23. 18:47백준/자바

 

10811번: 바구니 뒤집기

도현이는 바구니를 총 N개 가지고 있고, 각각의 바구니에는 1번부터 N번까지 번호가 순서대로 적혀져 있다. 바구니는 일렬로 놓여져 있고, 가장 왼쪽 바구니를 1번째 바구니, 그 다음 바구니를 2

www.acmicpc.net

도현이는 바구니를 총 N개 가지고 있고,
각각의 바구니에는 1번부터 N번까지 번호가 순서대로 적혀져 있다.

바구니는 일렬로 놓여져 있고, 가장 왼쪽 바구니를 1번째 바구니, 그 다음 바구니를 2번째 바구니, ...,
가장 오른쪽 바구니를 N번째 바구니라고 부른다. 

도현이는 앞으로 =바구니의 순서를 M번 역순으로 만들려고 한다.
도현이는 한 번 순서를 역순으로 바꿀 때, 순서를 역순으로 만들 범위를 정하고,
그 범위에 들어있는 바구니의 순서를 역순으로 만든다.

바구니의 순서를 어떻게 바꿀지 주어졌을 때,
바구니의 순서를 M번 역순으로 만든 다음,
바구니에 적혀있는 번호를 가장 왼쪽 바구니부터 출력하는 프로그램을 작성하시오.

 

5 4
1 2
3 4
1 4
2 2

 

바구니를 5개 만들고 4번동안 역순으로 만들어주는 시행을 할 것이다.

 

1. 1 2 시행결과 : 2 1 3 4 5

2. 3 4 시행결과 : 2 1 4 3 5

3. 1 4 시행결과 : 3 4 1 2 5

4. 2 2 시행결과 : 3 4 1 2 5

 

최종 결과: 3 4 1 2 5 가 출력되어야 한다.

 

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int N = sc.nextInt();
        int M = sc.nextInt();

        // 길이가 N인 int 형 바구니 넘버 배열을 생성
        int[] num = new int[N];

        // 바구니 넘버를 지정
        for(int k = 0 ; k < N ; k++){
            num[k] = k+1;
        }

        // for문 내에서 i j에 해당하는 값을 받음
        for(int l = 0 ; l < M ; l++ ) {
            int i = sc.nextInt();
            int j = sc.nextInt();

            if (i < j) {
                for (int t = 0; t <= (j - i)+1 / 3; t++, i++, j--) {
                    int a = num[i - 1];
                    num[i - 1] = num[j - 1];
                    num[j - 1] = a;
                }
            }

            if (i == j) { }

            }

        sc.close();

        // 바구니 번호를 공백으로 구분하여 출력
        for(int p = 0 ; p < N ; p++){
            System.out.print(num[p]+" ");
        }

    }

}
5 4
1 2
3 4
1 4
2 2
3 4 1 2 5

 

우걱우걱

저 예제 하나에 우겨 맞춘..... 알 수 없는 코드..

이마저도 다른 예제를 넣으면 틀리는데요

 

계속 고민하다가 인터넷의 코드들을 참고해보니

Stack을 사용한 글이 정말 많더라구요.

 

겁먹지 않고 적용해보기로 했습니다 :)

 

이 기회에 입출력 속도를 더 높일 수 있도록

BufferedReader
Bufferedwriter

방식도 사용하겠습니다.

더보기
 

[Java] 빠른 입출력을 위한 BufferedReader, BufferedWriter, StringTokenizer, StringBuilder

BufferedReader / BufferedWriter BufferedReader와 BufferdWriter는 버퍼를 사용하여 읽기와 쓰기를 하는 함수이다. 버퍼를 사용하지 않는 입력은, 키보드의 입력이 키를 누르는 즉시 바로 프로그램에 전달된다.

rlakuku-program.tistory.com

버퍼? 스캐너?

 

평소에는 Scanner 객체를 통해서 입출력을 해왔는데,

이는 쓰레기가 생길 때마다 밖에 나가서 일일이 버리는 것을 연상하면 되고,

 

버퍼를 쓰면

쓰레기가 생길 때 집 쓰레기통에 모아놨다가 꽉 차면 밖에 나가서 한 번에 버리는 것을 연상하면 됩니다.

 

버퍼를 사용하는 게 훨씬 효율적이고 빠릅니다.

 

 [입력] 

 

Scanner : 띄어쓰기와 개행문자를 경계로 해 입력값을 인식합니다.

그리고 Scanner.nextInt(), Scanner.nextLine() 이런식으로 바로 원하는 타입의 입력을 받을 수 있습니다.

 

BufferedReader : 개행문자만 경계로 인식하고 입력받은 데이터는 String으로 고정됩니다.

그래서 원하는 데이터 타입으로 바로 입력받지 못해 가공이 필요합니다.

 

그리고 예외처리가 반드시 필요합니다.

 

BufferedReader 사용 할 때 필요한 것 정리

1. 띄어쓰기 단위로 입력받기를 원할 때 공백 단위로 끊어 받기

- StringTokenizer의 nextToken() 함수 사용

- String.split() 함수 사용

 

2. 입력받고 형 변환하기

 

3. 예외처리하기

- try / catch문

- throws IOException

 

4. readline 메소드 사용

 

 [출력] 

System.out.println: 출력하고 개행처리를 함께해줘서 편리합니다!

BufferedWriter : 출력만 해서 따로 개행처리를 위해

.newLine() 이나 .write("\n")을 사용해야합니다.

 

또한 버퍼를 잡아 놓았기 때문에 반드시 사용 후에 버퍼 종료시키기~~!!!!

 

.flush() : 한 번 출력 후 다른 것도 출력하길 원할 때

.close(): 아예 출력스트림을 닫을 때

 

 

Stack
Stack의 가장 큰 특징은 LIFO(Last In First Out) 구조라는 것.
이는 뭐죠? 선입후출 입니다.

먼저 들어간 자료가 나중에 나온다는 구조.

역으로 받을 수 있다는 거죠!

 

1 2 3 4 5 를 push 받고

먼저 들어간 자료부터 pop 해준다면

5 4 3 2 1 !

원하는 답을 얻어낼 수 있을 것 같습니다.

 

스스로에게 친절하게 주석을 달면서 작성하겠습니다..

 

나의 정답 :

import java.io.*;
import java.util.Stack;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {     // 예외 처리 throws
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        StringTokenizer st = new StringTokenizer(br.readLine());

        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());

        // Scanner 쓸 때는 공백단위로 바로 끊어받아줬는데, BufferedReader를 쓰면서 StringTokenizer 사용해서 한번 더 과정 커져야 함.
//        int N = sc.nextInt();
//        int M = sc.nextInt();


        // 길이가 N인 int 형 바구니 넘버 배열을 생성
        int[] num = new int[N];

        // 바구니 넘버를 지정
        for (int k = 0; k < N; k++) {
            num[k] = k + 1;
        }

        // for문 내에서 i j에 해당하는 값을 받음
        for (int l = 0; l < M; l++) {
            // 새로운 Stack 생성하기
            Stack<Integer> stack = new Stack<>();
            st = new StringTokenizer(br.readLine());
            int i = Integer.parseInt(st.nextToken());
            int j = Integer.parseInt(st.nextToken());

            // push 쓰기!
            for (int o = i; o <= j; o++)
                stack.push(num[o - 1]);
            // pop해서 역으로 뒤집기!
            for (int o = i; o <= j; o++)
                num[o - 1] = stack.pop();

        }

        // 바구니 번호를 공백으로 구분하여 출력
        for (int p = 0; p < N; p++) {
            bw.write(num[p] + " ");
        }
        bw.close();
        br.close();
    }
}