All Articles

이차원 배열 알고리즘

TL;DR

최근 좋은 기회가 닿아 면접을 보게 되었다. 사실 면접 준비를 하면서 기술 질문이나 프로젝트 관련해서 질문을 할 것으로 예상했고 코딩테스트 또한 내가 풀어봤던 알고리즘 이거나 간단한 UI를 만드는 문제가 나올 줄 예상했지만, 역시나 면접은 예상하기 힘든 방향으로 흘러갔다.

사실 문제를 받자마자 벙졌다는 표현이 맞을 것 같다. 내가 한 번도 풀어보지 못한 방식의 2차원 배열의 요소를 특정 규칙으로 출력하는 내용이였다. 약 30분의 시간을 주셨고 중간에 힌트도 주셨지만 내 근심과 걱정으로 그득 한 표정과 함께 주신 힌트마저 잘못 판단하여 결국 풀지 못하고 처참한 결과를 내었다.

하지만, 면접 이후 결과가 어떻든 다시 와서 풀어보며 굉장히 간단한 코드에 한 번 놀랐고, 이런 방면으로 생각을 넓힐 수 있었던 것에 좋은 경험과 가르침을 얻고 왔다고 생각한다.

문제는 이중배열의 왼쪽부터 대각선 모양으로 출력하는 방식이였다. 예를 들자면,

[
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
]

위와 같은 2차원 배열의 내부 배열 길이는 모두 같고, [1, 4, 2, 7, 5, 3, 8, 6, 9] 순서로 출력하는 것이다.

알고리즘의 초반 설계와 규칙등을 노트에 그려보며 약 1시간 정도 걸려서 문제를 풀 수 있었고, 내가 푼 코드는 아래와 같다.

const diagonalPrint = m => {
  const xLen = m[0].length;
  const yLen = m.length;
  const totalCount = yLen + xLen;

  const result = [];

  for(let i = 0; i < totalCount; i++) {
    for(let j = 0; j <= i; j++) {
      const y = i - j;
      const x = j;

      if(y < yLen && x < xLen) result.push(m[y][x]);
    }
  };

  return result;
};

처음에 굉장히 갈팡질팡 했던 부분이 반복문의 기준 횟수를 어떻게 둬야 하는가 하는 점이었다. 두 번째 어려웠던 부분은 이차원 배열의 문제를 안풀어 봤던 탓에 값에 접근해야 할 방향을 잡지 못했던 것이었다. 테스트 도중 좌표 형식으로 접근해 보라는 힌트를 주셨지만, 당시에는 감이 오지 않았다.

면접 이후 혼자 풀어볼때는 처음 접근을 저 두부분에 집중해서 진행했다. 총 반복 횟수를 구하기 위해서 여러 시행착오를 겪으며 대각선 방향으로 선을 그어서 그 부분을 추가 반복문으로 접근하면 된다고 생각하여 for문 안에 for문을 돌리자고 생각했다. 이후, 대각선 한 개당 한 번의 반복을 진행하면 된다고 생각했고 이는 총 배열의 길이와 2차 배열 (내부 배열)의 길이를 더하면 나온다는 규칙을 발견했다.

그리고 추가 반복문인 J를 대각선의 요소가 가장 많았다가 점점 작아질 경우 어떻게 처리할 것인지에 대해 많이 고민했지만, i와 j로 가능한 모든 좌표를 찍을 수 있다고 가정했을 때 좌표의 x, y가 총 배열과 2차 배열의 총 길이보다 크면 안된다는 규칙을 발견해서 이를 적용 시켰다.

나에겐 굉장히 어려운 문제였지만, 어떤 면에서는 굉장히 쉽게 풀 수 있는 문제라고 생각하고 무엇보다

수학은 익숙해지는 것이다 - 폰노이만

이 말처럼 알고리즘을 많이 접해보고 생각해보는 것이 이러한 테스트에 대한 명확한 해결책이라고 생각한다. 다시 이런 황당함을 되풀이 하지 않기 위해 많이 풀어봐야겠다.

공부한 내용을 정리하는 공간으로 학습 중 습득한 내용이 정확하지 않은 정보를 포함할 수 있어 추후 발견시 수정하도록 하겠습니다.