[알고리즘] 2차원 배열 회전 + 간단 면접후기(phone screening)

오늘 면접에서 나와서 멘붕이었던 문제.

평소에는 쉬운 문제라고 그냥 정말 생각없이 넘어가거나, 작년 초쯤에 아주 쉽게 풀었던 기억이 있었는데.. 이런 배열 노가다 문제를 정확히 못풀다니 정말 아쉽기도 하고 한심하기도 하다.

정확히는 N의 크기가 3일 때, 즉 겉에만 돌리는 것은 성공했지만 이제 3 이상되는 크기에서는, i=0,4,5….N/2 까지 돌게 된다. 즉, 가에 있는 숫자들을 먼저 돌리고, 그 안쪽을 돌리고.. 이런식으로 돌리는 과정.

알고리즘

처음에 5×5을 하드코딩으로 아래와 같이 겉에만 회전하는 것을 성공해 두고

for(int j = 0 ; j < N - 1 ; j++){
    int k = matrix[0][j];
    matrix[0][j] = matrix[4 - j][i];
    matrix[4 - j][0] = matrix[4][4 - j];
    matrix[4][4 - j] = matrix[j][4];
    matrix[j][4] = k;
}

그다음에 루프를 하나 더 씌워서, 안쪽으로 진입할 수 있게 한 뒤

for(int i = 0 ; i < N/2 ; i++){
    System.out.println(" Loop #" + (i+1));
    for(int j = i ; j < N - i - 1 ; j++){

        int k = matrix[i][j];
        matrix[i][j] = matrix[N - 1 - j][i];
        matrix[N - 1 - j][i] = matrix[N - 1 - i][N - 1 - j];
        matrix[N - 1 - i][N - 1 - j] = matrix[j][N - 1 - i];
        matrix[j][N - 1 - i] = k;

        //System.out.println();

    }
}

다음에 뭔가 아쉬워서 rotate를 몇번 하는지 rotateCnt를 뒀다.

for(int x = 0 ; x < rotateCnt ; x++){
    for(int i = 0 ; i < N/2 ; i++){
        for(int j = i ; j < N - i - 1 ; j++){

            int k = matrix[i][j];
            matrix[i][j] = matrix[N - 1 - j][i];
            matrix[N - 1 - j][i] = matrix[N - 1 - i][N - 1 - j];
            matrix[N - 1 - i][N - 1 - j] = matrix[j][N - 1 - i];
            matrix[j][N - 1 - i] = k;

            //System.out.println();

        }
    }
}

아래는 완성 코드.

package com.matthewlab;

public class Rotate90 {
    public static int N = 10;
    public static void main(String[] args){
        int[][] matrix = new int[N][N];
        int k = 1;
        for(int i = 0 ; i < N; i++){
            for(int j = 0 ; j < N ; j++){
                matrix[i][j] = k++;
            }
        }

        print(matrix);
        rotate(matrix, 1);
        print(matrix);
    }

    public static int[][] rotate(int[][] matrix, int rotateCnt){

        for(int x = 0 ; x < rotateCnt ; x++){
            for(int i = 0 ; i < N/2 ; i++){
                for(int j = i ; j < N - i - 1 ; j++){

                    int k = matrix[i][j];
                    matrix[i][j] = matrix[N - 1 - j][i];
                    matrix[N - 1 - j][i] = matrix[N - 1 - i][N - 1 - j];
                    matrix[N - 1 - i][N - 1 - j] = matrix[j][N - 1 - i];
                    matrix[j][N - 1 - i] = k;

                    //System.out.println();

                }
            }
        }
        return matrix;
    }

    public static void print(int[][] matrix){
        for(int i = 0 ; i < N; i++){
            for(int j = 0 ; j < N ; j++){
                System.out.format("%4d", matrix[i][j]);
            }
            System.out.println();
        }
        System.out.println();
    }
}

후기

큰회사인 A사 면접이었는데, 면접의 약 60% 가량이 내 백그라운드 물어보는 것이었다. 과거 경험, 정확히 지금 하는일, 최근에 막혔던일/해결을 어떻게했나 등등. 이런거는 자주 생각해 둬서 최근에 JWT관련 라이브러리 바꾸면서 있던 문제 얘기해줬다. 그런데 문제는 희안한데서 발견됬다. 최근에 내가 살빼는 중이라 약 6키로 정도 감량했는데, 이거때문에 요즘 탄수화물을 거의 먹지 않는다. 문제는 탄수화물을 안먹으니 머리가 안돌아가고, 그래서 저 사실 위의 쉬운 문제도 왜이리 생각이 나지 않는지.. 머리가 파릿파릿 돌아가질 않는다. 게다가 영어도 잘 안들리고 말도 헛나오고.. 면접볼때는 최소한 전날에는 자유식을 해야하나 보다 싶더라.

그리고 코딩 문제를, 정말 CTCI 는 한 10번 돌렸고, 리트코드 한 150개, interviewcake도 많이봤고 했는데 이런게 도움이 안되는건 아니지만, 이젠 좀 시간을 재고 풀어야 할 필요성을 느낀다. 확실히 시간에 쫓기니깐 머리거 허얘지는 경향이 있다. 어차피 시스템 디자인이 아니고서야 아주 어려운 문제는 극히 드물게 나온다고 봐야겠고, 리트코드 easy/medium정도 난이도는 사실 금방 풀리기도 한다. 다만 그냥 하루에 codesignal이나 topcoder같은 컨테스트 중심적인 곳에서 푸는 것이 더 낫다는 생각. 여튼 연습만이 살길이다. 앞으로 더 있을 면접에서는 당황하지 말고 더 잘했으면.