[BOJ] 17276 배열 돌리기

2024. 6. 29. 10:37·Problem Solving/삼성 유형

출처: https://www.acmicpc.net/problem/17276

 

 

문제 설명

 크기가 n * n인 2차원 정수 배열 X가 있다. (n은 홀수) X를 45도만큼 시계방향 또는 반시계방향으로 돌리는 문제이다. 이때, 네 가지 경우 모두 원소의 기존 순서는 유지 되어야 하고, 회전하지 않는 원소들의 위치는 변하지 않는다.

 

Input:

T | int : 테스트 케이스의 수 (1 <= T <= 10)

 

board | int[][] : n * n인 2차원 정수 배열 (1 <= n*n < 250000)

 

D | int : 회전할 각도, 45의 배수 (0 <= |d| <= 360) 

 

tempBoard | int[][] : 회전시킨 배열을 담을 임시 2차원 배열 

 

 

 

 

실수 목록

40분이나 걸렸다. 실수다. 

 

 

내 코드

5000ms

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

public class Main {
    static int T;
    static int[][] board;
    static int N, D;

    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    public static void main(String[] args) throws IOException {
        T = Integer.parseInt(br.readLine());
        for (int tc = 0; tc < T; tc++) {
            input();

            solve();
        }
    }

    private static void solve() {
        int[][] tempBoard = new int[N][N];
        for (int i = 0; i < N; i++) {
            tempBoard[i] = board[i].clone();
        }

        if (D < 0)
            D += 360;

        for (int i = 0; i < D / 45; i++) {
            // 주 대각선 -> 가운데 열
            fromMainCrossToMediumCol(board, tempBoard);
            // 가운데 열 -> 부 대각선
            fromMediumColToSubCross(board, tempBoard);
            // 부 대각선 -> 가운데 행
            fromSubCrossToMediumRow(board, tempBoard);
            // 가운데 행 -> 주 대각선
            fromMediumRowToMainCross(board, tempBoard);

            for (int j = 0; j < N; j++) {
                board[j] = tempBoard[j].clone();
            }
        }

        print();
    }

    private static void print() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                System.out.print(board[i][j] + " ");
            }
            System.out.println();
        }
    }

    // 주 대각선 -> 가운데 열
    private static void fromMainCrossToMediumCol(int[][] board, int[][] tempBoard) {
        for (int i = 0; i < N; i++) {
            for (int j = i; j <= i; j++) {
                tempBoard[i][((N + 1) / 2) - 1] = board[i][j];
            }
        }
    }

    // 가운데 열 -> 부 대각선
    private static void fromMediumColToSubCross(int[][] board, int[][] tempBoard) {
        for (int i = 0; i < N; i++) {
            for (int j = i; j <= i; j++) {
                tempBoard[i][N - 1 - i] = board[i][((N + 1) / 2) - 1];
            }
        }

    }

    // 부 대각선 -> 가운데 행
    private static void fromSubCrossToMediumRow(int[][] board, int[][] tempBoard) {
        for (int i = 0; i < N; i++) {
            for (int j = i; j <= i; j++) {
                tempBoard[((N + 1) / 2) - 1][N - i - 1] = board[i][N - i - 1];
            }
        }
    }

    // 가운데 행 -> 주 대각선
    private static void fromMediumRowToMainCross(int[][] board, int[][] tempBoard) {
        for (int i = 0; i < N; i++) {
            for (int j = i; j <= i; j++) {
                tempBoard[N - i - 1][N - j - 1] = board[((N + 1) / 2) - 1][N - i - 1];
            }
        }
    }

    private static void input() throws IOException {
        StringTokenizer st;

        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        D = Integer.parseInt(st.nextToken());

        board = new int[N][N];

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
            }
        }
    }
}

 

 

 

다른 접근 방법 배우기, 내 코드에 적용하기

다른 사람의 풀이를 보고 나서 ..... 오..... 이래서 다른 사람이 작성한 코드를 꼭 봐야한다는 것을 깨달았다. 나는 무작정 문제에서 시키는 대로 구현하기 바빴지만(아니 사실 문제를 더 복잡하게 푼 것 같다) , 조금만 생각을 더 했더라면 간단하게 풀 수 있었을 것 같은 아쉬움이 든다. 

 

다른 사람 코드: 900ms

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

public class Main {
    static int n, d;
    static int[][] arr, copy;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        int t = Integer.parseInt(br.readLine());
        while(t-- > 0) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            n = Integer.parseInt(st.nextToken());
            d = Integer.parseInt(st.nextToken());
            if(d < 0) {
                d += 360;
            }
            d /= 45;
            arr = new int[n][n];
            copy = new int[n][n];
            for(int i=0; i<n; i++) {
                st = new StringTokenizer(br.readLine());
                for(int j=0; j<n; j++) {
                    arr[i][j] = Integer.parseInt(st.nextToken());
                    copy[i][j] = arr[i][j];
                }
            }
            while(d-- > 0) {
                rotate();
            }
            for(int i=0; i<n; i++) {
                for(int j=0; j<n; j++) {
                    sb.append(arr[i][j]).append(' ');
                }
                sb.append('\n');
            }
        }
        System.out.print(sb);
    }

    private static void rotate() {
        for(int i = 0; i < n ; i++){
            copy[i][n/2] = arr[i][i];
            copy[i][i] = arr[n/2][i];
            copy[n/2][i] = arr[n-i-1][i];
            copy[n-i-1][i] = arr[n-i-1][n/2];
        }

        for(int i=0; i<n; i++) {
            for(int j=0; j<n; j++) {
                arr[i][j] = copy[i][j];
            }
        }
    }
}

 

 

리펙토링 후 내 코드: 804ms

코드를 리펙토링하면서 시간이 너무 많이 걸려서 무슨 일인가 했더니 System.out.print()의 시간이 너무 느렸다. StringBuilder를 사용하고 5000ms -> 800ms로 줄어들었다.......... BufferedReader나 StringTokenizer를 전역 변수로 선언하는 게 편하긴 한데 이렇게 쓰면 안된다고 했다!! 

package algorithm.baekjoon.S2_17276_배열돌리기;

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

public class Main {
    static int T, N, D;
    static int[][] board, tempBoard;

    public static void main(String[] args) throws IOException {
        // input
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        T = Integer.parseInt(br.readLine());
        while (T-- > 0) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            N = Integer.parseInt(st.nextToken());
            D = Integer.parseInt(st.nextToken());
            if (D < 0) {
                D += 360;
            }
            D /= 45;

            board = new int[N][N];
            tempBoard = new int[N][N];

            for (int i = 0; i < N; i++) {
                st = new StringTokenizer(br.readLine());
                for (int j = 0; j < N; j++) {
                    board[i][j] = Integer.parseInt(st.nextToken());
                    tempBoard[i][j] = board[i][j];
                }
            }

            // solve
            solve();

            // print
            print();
        }
    }

    private static void solve() {
        while (D-- > 0) {
            rotate();
        }
    }

    private static void rotate() {
        for (int i = 0; i < N; i++) {
            tempBoard[i][N / 2] = board[i][i];
            tempBoard[i][N - i - 1] = board[i][N / 2];
            tempBoard[N / 2][N - i - 1] = board[i][N - i - 1];
            tempBoard[N - i - 1][N - i - 1] = board[N / 2][N - i - 1];
        }
        for (int i = 0; i < N; i++) {
            board[i] = tempBoard[i].clone();
        }
    }

    private static void print() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                sb.append(board[i][j]).append(" ");
            }
            sb.append("\n");
        }
        System.out.print(sb);
    }
}

 

 

 

'Problem Solving/삼성 유형' 카테고리의 다른 글
  • [BOJ] 20056번: 마법사 상어와 파이어볼
kimdozzi
kimdozzi
끝까지 포기하지 않으면, 내가 다 이겨!
  • kimdozzi
    도브로
    kimdozzi
  • 전체
    오늘
    어제
    • 분류 전체보기 (132)
      • Problem Solving (49)
        • Baekjoon (29)
        • Programmers (0)
        • LeetCode (17)
        • 삼성 유형 (2)
      • Computer Science (27)
        • Operating System (2)
        • Algorithms (13)
        • Network (6)
        • DataBase (6)
      • Backend (33)
        • JavaScript (0)
        • TypeScript (6)
        • Java (7)
        • Spring Boot (7)
        • Spring Security (6)
        • JPA (2)
        • Mybatis (1)
        • Junit5 (1)
        • Redis (3)
      • DevOps (14)
        • Git, Github (5)
        • docker (4)
        • AWS (3)
        • nginx (2)
      • etc (6)
        • IntelliJ (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 티스토리
    • 설정
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    구간 업데이트
    CORS
    docker
    티스토리챌린지
    삼성기출
    인덱스 시그니처
    인덱서블 타입
    구간합
    Bucket
    S3
    세그먼트 트리
    imos법
    docker image
    누적합
    오프라인 쿼리
    컨테이너
    타입스크립트
    python
    인터페이스
    PrefixSum
    알고리즘
    백준
    segment tree
    온라인 쿼리
    파이썬
    interface
    도커
    오블완
    AWS
    TypeScript
    점 업데이트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
kimdozzi
[BOJ] 17276 배열 돌리기
상단으로

티스토리툴바