PS/PS Log
23.05.09. 풀었던 문제들
hyelie
2023. 5. 9. 10:22
Leetcode 54. Spiral Matrix
첫 접근 (wrong)
처음에는 위 그림처럼 풀려 했다. 결국 spiral로 풀기 때문에 겉면만 벗겨가면서 풀면 된다고 생각했기 때문이고, 가능하면 모든 변을 동일하게 접근하는 게 구현에서 쉬울 거라 생각했다.
일단 벗기는 회수는 row size를 m, col size를 n이라 했을 때 min((m+1)/2, (n+1)/2)이다. 이건 뭐 간단하게 나오는 답.
그러나 복잡한 경우는 matrix가 3 by 3라서 제일 겉면을 벗겼는데, 안에 딱 1개의 element만 남는 경우이다. [시작점]부터 [끝점-1]까지만 접근하기 때문에 이런 경우를 처리할 수 없다.
올바른 접근 (correct)
결국 한 번은 전부 다에 접근해야 한다. 구현의 편의를 위해 row 시작점/끝점, col 시작점/끝점의 좌표를 기억하자. 그리고 자연스럽게 spiral로 돌리면 위 그림처럼 돌게 된다.
각 탐색이 끝나면 해당 위치는 더 이상 탐색하지 않기에 그 값을 갱신한다.
- 처음에는 rowStart row에 있는 모든 element를 담는다. [rowStart, 0], [rowStart + 1, 0] , ... , [rowEnd, 0]이 그것이다. 이 탐색이 끝나면 rowStart++해준다.
- 다음으로 colEnd col에 있는 모든 element를 담는다. [1, colEnd], [2, colEnd], ... , [rowEnd, colEnd]가 그것이다. 이 탐색이 끝나면 해당 colEnd는 더 이상 탐색하지 않으므로 colEnd--해 준다.
- 같은 방법으로 아래쪽을 벗긴다. 이 때, rowStart가 rowEnd와 같으면 위쪽과 같은 row를 탐색하는 것이므로 패스한다.
- 같은 방법으로 왼쪽을 벗긴다 .이 때 colStart가 colEnd와 같으면 오른쪽과 같은 col을 탐색하는 것이므로 패스한다.
// Runtime 0 ms Beats 100%
// Memory 6.8 MB Beats 69.57%
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int m = matrix.size(), n = matrix[0].size(), cnt = 0;
vector<int> answer;
int numRepeat = min((m+1)/2, (n+1)/2);
int rowStart = 0, rowEnd = m-1, colStart = 0, colEnd = n-1;
for(int k = 0; k<numRepeat; k++){ // cycle 시작지점이 몇 개인지
for(int j = colStart; j<=colEnd; j++){
answer.push_back(matrix[rowStart][j]);
}
rowStart++;
for(int i = rowStart; i<=rowEnd; i++){
answer.push_back(matrix[i][colEnd]);
}
colEnd--;
if(rowEnd >= rowStart){
for(int j = colEnd; j>=colStart; j--){
answer.push_back(matrix[rowEnd][j]);
}
rowEnd--;
}
if(colEnd >= colStart){
for(int i = rowEnd; i>=rowStart; i--){
answer.push_back(matrix[i][colStart]);
}
colStart++;
}
}
return answer;
}
};
시간복잡도
결국 모든 matrix를 순회해야 하므로 row size를 m, col size를 n이라 할 때 O(mn)이다.
공간복잡도
추가 공간은 사용하지 않으므로 O(1)
후기
구현 빡세..