JavaScript/알고리즘

프로그래머스 정수를 나선형으로 배치하기 JS ( Array(), Array.from(), 중첩for문, n x n 2차원배열만들기 )

hihiha2 2023. 6. 10. 15:04
반응형

문제 설명

양의 정수 n이 매개변수로 주어집니다. n × n 배열에 1부터 n2 까지 정수를 인덱스 [0][0]부터 시계방향 나선형으로 배치한 이차원 배열을 return 하는 solution 함수를 작성해 주세요.

 

 

 

✅ 코드

function solution(n) {
  const result = Array.from(Array(n), () => Array(n).fill(0)); // n x n 배열 생성
  
  let num = 1; // 시작 숫자
  let row = 0; // 행의 시작 인덱스
  let col = 0; // 열의 시작 인덱스

  for (let i = n; i > 0; i -= 2) {
    // 오른쪽으로 이동
    for (let j = 0; j < i; j++) {
      result[row][col] = num++;
      col++;
    }
    col--;
    row++;
    
    // 아래로 이동
    for (let j = 0; j < i - 1; j++) {
      result[row][col] = num++;
      row++;
    }
    row--;
    col--;
    
    // 왼쪽으로 이동
    for (let j = 0; j < i - 1; j++) {
      result[row][col] = num++;
      col--;
    }
    col++;
    row--;
    
    // 위로 이동
    for (let j = 0; j < i - 2; j++) {
      result[row][col] = num++;
      row--;
    }
    row++;
    col++;
  }
  
  return result;
}

이 문제는 해결법이 떠오르지가 않아서🥲  많이 고생한 문제이다.

우선 n*n형태의 배열을 형성하는 법을 몰랐고, 한변의 길이를 이용해서 푼다는 생각을 못했다. 

 

한변의 길이 i로 설정하고 그 값을 for문을 통해서 조정하면서 반복하는것이 이 문제의 핵심이라고 생각했다.

 

코드를 순서대로 해석하면,

1️⃣ n x n 배열 생성 (초기값 0으로)

const result = Array.from(Array(n), () => Array(n).fill(0)); // n x n 배열 생성

Array.from()과 Array()를 이용해서 n*n의 배열을 생성한다.

그런다음, fill(0을 통해서 초기값을 0으로 설정한다.

 

 

2️⃣ num, row, col 선언, 값 할당

  let num = 1; // 시작 숫자
  let row = 0; // 행의 시작 인덱스
  let col = 0; // 열의 시작 인덱스

실제값이 들어가는 것을 num으로 이름을 짓고 1을 처음값으로 넣어준다. (맨 처음에 들어갈 값이 1이므로)

각 배열의 위치를 이동시킬때 행과 열의 인덱스를 이용할 것이므로, 열의 인덱스의 이름은 row로 행의 인덱스의 이름은 col이라고 지어주었다. 그런다음 각각 0의 값을 넣었다. (인덱스의 시작이 [0,0]이므로)

 

 

 

3️⃣ 한변의 길이 i 를 이용해서 for문 만들기

 for (let i = n; i > 0; i -= 2) {
  ...
}

 

for (let i = n; i > 0; i -= 2)은 배열을 나선형으로 순회하기 위한 반복문

이 구문에서 i는 현재 반복 단계에서 탐색할 숫자를 배치할 수 있는 한 변의 길이를 나타낸다.

 

배열이 나선형으로 돌면서 길이가 계속 변화되는데, 그때마다 길이가 2씩 줄어든다. 

 

그림으로 나타내면 아래와 같이 나타낼 수 있다.

파란색처음의 한변의 길이이다. 이때 한변의 길이 i = n과 같다 (n=4로 설정했을때 예시)

한바퀴를 다 돌고 안쪽 나선으로 들어갈때 i의 길이는 2가 줄어든다. (안쪽 빨간색의 길이를 보면 된다)

이렇게 한바퀴를 반복할때마다 i의 길이가 2씩 줄어드므로 for문을 이용해서 i-2를 해준다.

처음 한변의 길이는 n과 같으므로 i=n으로 초기값을 설정하고, 길이가 0보다 클때까지 반복한다.

 

나선형으로 순회할때는 이렇게 가장 큰 사각형안의 더 작은 사각형, 그 안의 더 작은 사각형.. 이런식으로 반복된다.

 

이렇게 배열의 길이를 이용하고, 또 길이가 한바퀴를 돌때마다 -2가 된다는 것이 문제의 핵심인것 같다고 생각했다.

 

 

4️⃣ 중첩 for문을 이용한 위치이동

    // 오른쪽으로 이동
    for (let j = 0; j < i; j++) {
      result[row][col] = num++;
      col++;
    }
    col--;
    row++;

바깥쪽 for문이 배열의 길이 i를 이용한다고 하면, 안쪽은 중첩 for문을 이용해서 위치를 이동하면서 num의 값을 조정한다.

 

코드는 나선형이므로 오른쪽 - 아래 - 왼쪽 - 위쪽 순으로 반복되며

오른쪽으로 이동하는 코드를 예시로 보면 위의 코드와 같다.

 

위치의 이동을 위해서 j를 이용하고 j는 현재 이동할 칸수를 의미한다.

예시로 n이 4라고 하면, j는 0부터 0,1,2,3이 될것이다. (0 부터 i-1까지 반복하면서 숫자를 배치하고 총 이동할 칸수는 i만큼이다)

 

for문이 반복되면서 num에 1씩을 더하면서 위치가 이동되는데, 처음에는 오른쪽으로 이동해야하기때문에 col에만 +1씩 해준다.

result[0][0] = 1

result[0][1]  = 2

result[0][2] = 3

result[0][3] = 4

for문이 반복되면서 위와 같이 값이 들어가고,  j=4가되면 i와 같이지므로 반복을 중단하고 for문을 빠져나온다.

 

이때 col은 안에서 이미 한번 더 더해줬기때문에 col의 인덱스 +1의 값이므로 바깥쪽에서 다시 한번 빼줘야 배열의 길이만큼으로 돌아온다.

 

그런 다음은 아래로 이동해야되기때문에 row에 +1을 해준다.

위와 같은 원리로 아래, 왼쪽, 위로 이동하는 코드를 모두 짜준다.

 

이때 주의해야 할 점은 나머지코드는 모두 비슷하지만 한변의 길이는 각각 다르기때문에 i의 길이가 줄어들었는지 아닌지를 반영하여 코드를 짜야한다.

아래와 왼쪽으로 이동할때는 길이가 1이 줄었기 때문에 j<i-1이 되고, 위로 이동할때는 길이가 2가 줄었기때문에 j<i-2가 된다.

 

이런식으로 위치를 이동하면서 num+을 해주며 i가 0보다 클때까지 반복된다.

 

 

 

💻  학습한 것

✔️ Array()와 Array.from()의 차이점

➡️Array()는 간단한 배열 생성이나 초기화에 사용되고, Array.from()은 기존 배열이나 이터러블 객체를 변환하거나 새로운 배열을 생성

 

 

Array(): 생성자 함수, 새로운 Array 객체를 생성

    [element0, element1, ..., elementN]

    new Array(element0, element1[, ...[, elementN]])
    new Array(arrayLength)

Array()에 하나의 인자만 넣으면 배열의 길이를 나타낸다. 넣어준 숫자만큼의 length를 가진 Array가 생성된다.

 

 

Array.from():  유사 배열 객체(array-like object)나 반복 가능한 객체(iterable object)를 얕게 복사해 새로운Array 객체를 생성

    Array.from(arrayLike[, mapFn[, thisArg]])

mapFn

배열의 모든 요소에 대해 호출할 맵핑 함수.

 

Array.from()의 두번째 인자함수를 넣을 수 있다.

콜백 함수를 제공할 경우, 이 함수는 새로 생성된 배열의 각 요소에 대해 실행되며, 요소의 값을 결정한다.

 

 

✔️ n x n 2차원 배열만들기

Array.from(Array(n), () => Array(n))

 

Array(n)을 이용해서 length가 n인 배열을 만들고 Array.from의 두번째 인자로 함수를 넣어서 n x n의 2차원 배열을 생성할 수 있다.

 

 

 

 

🙋‍♀️ 내생각

배열을 나선형으로 만들거나 2차원배열을 만드는 것 모두 약간 생소해서 풀기가 어려운 문제였는데, 나만 그랬던 건 아닌것같다. 

다른 사람의 풀이를 보다가 제일 좋아요를 많이 받은 코드는 보면서 웃음 터짐 ㅋㅋㅋㅋ

일일이 노다가로 하나하나 값을 다 넣어서 푼 코드였다  ㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

댓글도 웃겼음 😇😇😇

 

반응형