2023
03.20

출처: 프로그래머스 코딩 테스트 연습
https://school.programmers.co.kr/learn/courses/30/lessons/77485

 

 

개인적으로 제일 싫어하는 유형의 문제.

문제만 길고 내용은 노가다에 가깝다.

 

나의 풀이

public int[] solution(int rows, int columns, int[,] queries) 
{
    int[] answer = new int[queries.GetLength(0)];
    int[,] matrix = new int[rows, columns];

    // 매트릭스 채우기
    int count = 0;
    for(int y = 0; y < rows; ++y)
    {
        for(int x = 0; x < columns; ++x)
            matrix[y, x] = ++count;
    }

    // 회전
    for(int i = 0; i < queries.GetLength(0); ++i)
    {
        Rotate(matrix, queries[i, 0] - 1, queries[i, 1] - 1,
               queries[i, 2] - 1, queries[i, 3] - 1, out int min);

        answer[i] = min;
    }

    return answer;
}

void Rotate(int[,] matrix, int y1, int x1, int y2, int x2, out int min)
{
    if(y1 == y2 && x1 == x2)
    {
        min = matrix[y1, x1];
        return;
    }

    var list = new List<(int y, int x)>();

    for(int i = x1; i <= x2; ++i) // 왼쪽위 -> 오른쪽 위
        list.Add((y1, i));

    for(int i = y1 + 1; i <= y2; ++i) // 오른쪽 위 -> 오른쪽 아래
        list.Add((i, x2));

    for(int i = x2 - 1; i >= x1; --i) // 오른쪽 아래 -> 왼쪽 아래
        list.Add((y2, i));

    for(int i = y2 - 1; i >= y1; --i) // 왼쪽 아래 -> 왼쪽 위 (시작 포인트는 중복)
        list.Add((i, x1));

    int before = int.MaxValue;
    (int y, int x) start = list[0];
    min = matrix[start.y, start.x]; // 임시값

    for(int i = 0; i < list.Count; ++i)
    {
        (int y, int x) cur = list[i];

        int temp = matrix[cur.y, cur.x];
        matrix[cur.y, cur.x] = before;
        before = temp;

        if(temp < min)
            min = temp;
    }
}

회전 범위에 해당하는 좌표들을 List Tuple에 넣어놓고서

다시 List를 순회하면서 한 칸씩 밀어내는 방식으로 풀었다.

 

명시성을 위해서 평소에는 이런식으로 코딩을 하는데

성능을 생각한다면 리스트를 만드는 대신 순회를 한 번 할 때 넣는 방식이 나을 듯.

 

아무튼 영양가가 없다.

 

[ 주의할 점 ]

행(row)과 열(column)이 주어지면

매트릭스의 크기는 new int[row, column] 이며,

접근할 때는 y번째 행, x번째 원소라는 의미로 matrix[y, x] 로 쓴다.

 

수학 그래프를 그릴 때 쓰는 x, y 좌표계와는 반대니 주의.