Algorithm/Swift

[Programmers] 행렬 테두리 회전하기 (Swift)

Minny27 2021. 7. 10. 02:11

문제 : 

https://programmers.co.kr/learn/courses/30/lessons/77485

 

코딩테스트 연습 - 행렬 테두리 회전하기

6 6 [[2,2,5,4],[3,3,6,6],[5,1,6,3]] [8, 10, 25] 3 3 [[1,1,2,2],[1,2,2,3],[2,1,3,2],[2,2,3,3]] [1, 1, 5, 3]

programmers.co.kr

 

1. 문제 이해하기

  • rows(행), columns(열)이 주어지고 (row x columns) 크기의 행렬에 좌에서 우로 1부터 숫자가 순서대로 적혀있습니다.
  • queries가 2차원 배열로 주어지고, 각 query에는 [x1, y1, x2, y2] 형태로 저장되어 있습니다.
  • 이는 x1 행 y1열부터 x2 행 y2 열까지의 영역에 해당하는 직사각형 테두리에 있는 숫자들을 한 칸씩 시계방향으로 회전.
  • 해당 테두리에 있는 숫자들 중 가장 작은 값들을 정수형 배열로 출력
  • rows, columns는 모두 2 이상 100 이하의 자연수, queries(회전 횟수)는 최대 10000 이하

 

2. 문제 풀이 생각하기

  1. 먼저 쿼리 개수가 최대 10000, 행렬의 최대 크기(100*100)이라고 했을 때, 테두리 한 번씩만 진행하기 때문에 시간 복잡도는 크게 고려하지 않아도 되겠다고 생각했습니다.
  2. 먼저 1부터 연속된 숫자를 저장할 (rows * columns)의 크기의 배열 g에 1부터 순서대로 저장합니다.
  3. 쿼리마다 주어지는 (x1, y1, x2, y2)를 인자로 받을 수 있는 함수 rotate를 생성합니다.
  4. tmp에 테두리에서 제일 왼쪽 위에 있는 값을 넣고 오른쪽, 아래, 왼쪽, 위 순으로 swap을 진행합니다. 이때 방향마다의 첫 시작점과 끝점, 그리고 행과 열을 주의해서 구현해야 합니다.

 

[Step 1] 오른쪽 스왑

 

[Step 2] 아래 스왑

해당 방식을 반복

여기서 반복문의 시작(스왑의 시작)은 항상 테두리 다음 칸입니다.

 

3. 차근차근 구현하기

import Foundation

func solution(_ rows:Int, _ columns:Int, _ queries:[[Int]]) -> [Int] {
    var ans = [Int]()
    var g : [[Int]] = Array(repeating: Array(repeating: 0, count: columns), count: rows)
    var k = 1
    for i in 0..<rows {
        for j in 0..<columns {
            g[i][j] = k
            k += 1
        }
    }
    
    func rotate(_ r1:Int, _ c1:Int, _ r2:Int, _ c2:Int) -> Int {
        var tmp = g[r1 - 1][c1 - 1]
        var minValue = tmp
        var (i, j) = (r1 - 1, c1 - 1)
        
        //오른쪽
        for j in c1..<c2{
            minValue = min(minValue, g[i][j])
            (tmp, g[i][j]) = (g[i][j], tmp)
        }
        
        j = c2 - 1
        
        //아래
        for i in r1..<r2{
            minValue = min(minValue, g[i][j])
            (tmp, g[i][j]) = (g[i][j], tmp)
        }

        i = r2 - 1
        
        //왼쪽
        for j in stride(from: c2 - 2, to: c1 - 2, by: -1) {
            minValue = min(minValue, g[i][j])
            (tmp, g[i][j]) = (g[i][j], tmp)
        }
        
        j = c1 - 1
        
        //위
        for i in stride(from: r2 - 2, to: r1 - 2, by: -1) {
            minValue = min(minValue, g[i][j])
            (tmp, g[i][j]) = (g[i][j], tmp)
        }
        return minValue
    }
    
    for matrix in queries {
        ans.append(rotate(matrix[0], matrix[1], matrix[2], matrix[3]))
    }
    return ans
}

 

4. 피드백

  • 처음에 x, y를 x축, y축으로 반대로 생각해서 생각보다 오래 걸렸던 것 같습니다. 문제를 더 꼼꼼히 읽는 습관을 들여야겠습니다.