CodeWars 여든 한 번째 문제

Updated:

Snail

public static int[] snail(int[][] array) {

    if(array == null || array[0].length == 0) {
        return new int[] {};
    }

    int[] result = Arrays.copyOf(array[0], array.length * array.length);

    boolean turn = true;
    int length = array.length-2; 
    int x = 0;
    int y = array.length-1;

    int nextX = array.length-1;
    int nextY = 0;

    for(int i = array.length ; i < result.length ; i++) {
        if(turn) {
            if(x < nextX) {
                x++;
            } else {
                y--;
            }
        } else {
            if(x > nextX) {
                x--;
            } else {
                y++;
            }
        }

        result[i] = array[x][y];

        if(x == nextX && y == nextY) {
            nextX = nextX + (turn? -length : length);
            nextY = nextY + (turn? length : -length);
            length-=1;
            turn = !turn;
        }
    }

    return result;
}
  • 처음으로 4kyu를 풀었다. 5kyu까진 풀었었는데 진호가 4kyu를 푼다고 해서 나도 도전했다.
  • 문제는 평소 한 두번 봤을 법한 문제였다. 시계 방향으로 안쪽으로 돌아가면서 배열을 출력하는 문제다.
  • 나의 크게 경우의 수를 2가지로 나누었다. x가 아래로, y가 왼쪽으로 가는 방향과 x가 위로, y가 오른쪽으로 가는 방향 이렇게 나누었다.
  • 그리고 방향을 바꾸어주는 turn 변수를 통해서 다음 x,y 지점을 계산해 내었다.
  • 주어진 배열이 4X4라면 x,y가 (0,3)부터 시작한다. (첫 행은 항상 똑같이 출력 하므로 처음에 바로 결과 값에 넣음) 그럼 다음 x,y의 목표 지점이 (3,0)이므로 x를 먼저 증가시키고 y를 감소 시킨다.
  • 그리고 다음 x,y 목표 지점이 (1,2)이므로 x를 감소 시키고 다음 y를 증가시킨다.
public static int[] snail(int[][] array) {
    if (array[0].length == 0) return new int[0];
    int n = array.length;
    int[] answer = new int[n*n];
    int index=0;
    for (int i = 0; i<n/2; i++){
        for (int j = i; j < n-i; j++) answer[index++] = array[i][j];
        for (int j = i+1; j < n-i; j++) answer[index++] = array[j][n-i-1];
        for (int j = i+1; j < n-i; j++) answer[index++] = array[n-i-1][n-j-1];
        for (int j = i+1; j < n-i-1; j++) answer[index++] = array[n-j-1][i];
    }
    if (n%2 != 0) answer[index++] = array[n/2][n/2];
    return answer;
} 
  • Best 코드의 경우 한 바퀴 도는 것을 한 사이클로 보았다.

  • 그리고 그 사이클은 배열 크기의 절반이다. 예를 들어 6X6행렬의 경우 3번이다. (그림 그려보면 암)

  • 그리고 한 사이클은 꺾여지는 순간인 4번을 각 for문 통해서 나누었다. 그리고 위에 보다시피 사이클을 나타내는 i변수를 통해서 각 꺾여지는 순간의 조건들을 잘 계산해 결과 값을 가져왔다.

  • 그리고 마지막으로 행렬의 크기가 홀수 인 경우는 항상 가운데가 남기 때문에(한 사이클이 즉 사각형인데 홀수이면 마지막 1개 행렬만 남음) 넣어주고 return한다.