THE DEVLOG

scribbly.

자바스크립트 기본 알고리즘

2023.01.08 01:26:42

효율성

자릿수의 합

오름차순으로 정렬이 된 두 배열이 주어지면 두 배열을 오름차순으로 합쳐 출력하는 프로그램을 작성하세요.

  • 입력설명
    첫 번째 줄에 첫 번째 배열의 크기 N(1<=N<=100)이 주어집니다.
    두 번째 줄에 N개의 배열 원소가 오름차순으로 주어집니다.
    세 번째 줄에 두 번째 배열의 크기 M(1<=M<=100)이 주어집니다.
    네 번째 줄에 M개의 배열 원소가 오름차순으로 주어집니다.
    각 리스트의 원소는 int형 변수의 크기를 넘지 않습니다

  • 출력설명
    오름차순으로 정렬된 배열을 출력합니다.

  • 입력예제

3
1 3 5
5
2 3 6 7 9

  • 출력예제

1 2 3 3 5 6 7 9

  • 답안1
//인풋을 입력받습니다.
const fs = require("fs");
const filePath =
  process.platform === "linux" ? "/dev/stdin" : __dirname + "/input.txt";

const input = fs.readFileSync(`${filePath}`).toString().trim().split("\r\n");

//solution함수 안에 답안을 작성하세요.
function solution(input) {
  const firstArr = input[1].split(" ").map(Number);
  const secondArr = input[3].split(" ").map(Number);
  const answer = [];

  while (true) {
    if (!firstArr.length || !secondArr.length) {
      // 만일 두 배열 중 하나라도 비어있으면 정답에 배열을 합친 후 종료한다.
      answer.push(...firstArr, ...secondArr);
      console.log(answer.join(" "));
      break;
    } else if (firstArr[0] < secondArr[0]) {
      //배열 중 작은 숫자를 shift해서 answer에 추가한다.
      answer.push(firstArr.shift());
    } else {
      answer.push(secondArr.shift());
    }
  }
}

solution(input);
  • 풀이 해설
    while 문을 이용하여 배열의 가장 앞의 값을 비교한 후, 작은 값을 shift로 반환한다. 만일 두 배열 중 하나라도 길이가 0이 되면 배열들을 정답에 합친 후 정답을 출력하고 while문을 탈출한다.
    해당 답안의 문제는 shift를 사용한다는 점이다. shift는 O(n)의 시간 복잡도를 가질 수 있다.
    포인터를 이용하여 아래와 같이 수정할 수 있다.

  • 답안2 (포인터를 이용한 답안)

//인풋을 입력받습니다.
const fs = require("fs");
const filePath =
  process.platform === "linux" ? "/dev/stdin" : __dirname + "/input.txt";

const input = fs.readFileSync(`${filePath}`).toString().trim().split("\r\n");

//solution함수 안에 답안을 작성하세요.
function solution(input) {
  const firstArrLength = Number(input[0]);
  const firstArr = input[1].split(" ").map(Number);
  const secondArrLength = Number(input[2]);
  const secondArr = input[3].split(" ").map(Number);
  const answer = [];

  //포인터를 만든다
  let firstIdx = 0;
  let secondIdx = 0;

  //두 배열 중 하나라도 포인터가 마지막에 닿으면 반복문을 종료한다.
  while (firstIdx < firstArrLength && secondIdx < secondArrLength) {
    //두 배열 중 포인터가 가르키는 값을 비교하여 작은 값을 답에 push하고 해당하는 포인터를 오른쪽으로 이동한다.
    if (firstArr[firstIdx] < secondArr[secondIdx]) {
      answer.push(firstArr[firstIdx]);
      firstIdx = firstIdx + 1;
    } else {
      answer.push(secondArr[secondIdx]);
      secondIdx = secondIdx + 1;
    }
  }

  //포인터를 기준으로 마지막까지의 값들을 answer에 push한다.
  //해당 과정은 slice메서드가 아닌 for문으로 대체하여 공간복잡도를 줄일 수 있다.
  answer.push(...firstArr.slice(firstIdx, firstArrLength));
  answer.push(...secondArr.slice(secondIdx, secondArrLength));
  console.log(answer.join(" "));
}

solution(input);
  • 자바스크립트 문법 팁
    Array.Prototype.slice(시작인덱스, 마지막 인덱스) : slice는 마지막 인덱스 '전'까지 반환함에 유의하며 사용하자. slice는 기존 배열을 얕은 복사하여 새로운 배열을 반환한다.