https://school.programmers.co.kr/learn/courses/30/lessons/181832
양의 정수 n이 매개변수로 주어집니다. n × n 배열에 1부터 n2 까지 정수를 인덱스 [0][0]부터 시계방향 나선형으로 배치한 이차원 배열을 return 하는 solution 함수를 작성해 주세요.
제한사항
- 1 ≤ n ≤ 30
lv0이라 만만하게 봤는데 정답률이 낮은 이유가 있었다.
특별한 알고리즘이나 자료구조는 쓰지 않는 구현 문제이지만 이차배열을 나선형으로 순회하는 것을 40분 동안 고민했다.
이런건 그냥 뇌를 비우고 한 스텝씩 실수 없이 처리하는게 방법인 것 같다.
currNum 1부터 시작해서 n*n까지 while을 돌리며 → ↓ ← ↑ 순으로 이차배열을 순회했다.
이동방향은 0: → 1: ↓ 2: ← 3: ↑ 이 처럼 숫자로 판단했고 방향이 바뀔때마다 ++ 한 뒤 Mod로 갱신해주었다.
현재row = 0, 현재 col = 0, 현재 이동하는 방향 = 오른쪽 으로 초기 세팅을 하고
한 방향으로 이동할 때마다 다음 좌표가 유효한지 확인한다
- 유효하면 계속 동일한 방향으로 이동한다
- 유효하지 않으면 다음 방향으로 바꿔준다.
단 주의할 점이 있는데 순회 할 수록 다음 좌표의 유효성을 판단하는 범위가 좁아진다는 것이다
예를 들어 첫번째 순회의 → 로 이동할 때 다음 좌표가 0과 4사이여야지만 유효하다
하지만 두번째 순회에서 → 로 이동할 때는 1과 3사이만 유효하다
이를 padding으로 기록했고 ← 에서 ↑ 로 바뀔때 padding++해주었다.
풀이 (성공)
function solution(n) {
var answer = Array.from({ length: n }, () =>
Array.from({ length: n }, () => 0)
);
const lastNum = n * n;
let currRow = 0;
let currCol = 0;
let currNum = 1;
let currDir = 0; // 0: right, 1: down, 2: left, 3: top
let padding = 0;
while (currNum <= lastNum) {
answer[currRow][currCol] = currNum;
// 현재 진행방향이 오른쪽
if (currDir === 0) {
// 그 다음 좌표가 범위를 넘어가면 진행방향 바꾸기
if (currCol + 1 >= n - padding) {
currDir = getNextDir(currDir);
currRow++;
} else {
currCol++;
}
}
// 현재 진행방향이 아래쪽
else if (currDir === 1) {
// 그 다음 좌표가 범위를 넘어가면 진행방향 바꾸기
if (currRow + 1 >= n - padding) {
currDir = getNextDir(currDir);
currCol--;
} else {
currRow++;
}
}
// 현재 진행방향이 왼쪽
else if (currDir === 2) {
// 그 다음 좌표가 범위를 넘어가면 진행방향 바꾸기
if (currCol - 1 < 0 + padding) {
currDir = getNextDir(currDir);
currRow--;
padding++;
} else {
currCol--;
}
} else {
// 그 다음 좌표가 범위를 넘어가면 진행방향 바꾸기
if (currRow - 1 < 0 + padding) {
currDir = getNextDir(currDir);
currCol++;
} else {
currRow--;
}
}
currNum++;
}
return answer;
}
function getNextDir(currDir) {
return currDir + 1 <= 3 ? currDir + 1 : (currDir + 1) % 4;
}