가치투자자

[BOJ] 2751번 : 수 정렬하기2 본문

Problem Solving/BOJ

[BOJ] 2751번 : 수 정렬하기2

미주민 2023. 3. 30. 16:27
728x90
반응형

백준 2751번 : 수 정렬하기2

🔗 문제 링크

https://www.acmicpc.net/problem/2751

 

2751번: 수 정렬하기 2

첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 절댓값이 1,000,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.

www.acmicpc.net

 


💬 문제

 정렬 알고리즘 에 대한 이해가 있다면, 충분히 풀 수 있는 문제다.

 

  1. 1번째 줄에 정렬해야 하는 수의 개수 N이 주어진다.
  2. 2번째 줄부터 총 N개의 수가 주어지며, 이를 배열 arr로 받아준다.
  3. 배열 arr를 오름차순으로 정렬하여 출력해준다.

 


💡 입력값 받아오기

JavaScript로 풀 경우, 입력값(input)을 어떻게 받아와야 할 지가 중요하다.

이 문제에서는 1번째 줄에 N을 주고, 그 다음줄부터 N개의 수가 입력값으로 주어졌다.

 

 

 

입력값을 받아오는 것과 관련해 더 자세한 내용은 아래 링크를 참고 바란다.

https://valueengine.tistory.com/2

 

[BOJ] Node.js로 백준(BOJ) 푸는 법 및 VSCode 환경 세팅

1. Node.js fs모듈 사용법 백준에서 JavaScript로 문제를 풀기 위해선 Node.js를 사용해야 하며, 이때 readline 모듈이나 fs 모듈로 입력값(input)을 받아와야 한다. 이 중 속도나 코드의 길이, 작성 편리성에

valueengine.tistory.com

 

728x90

 


💻 풀이

이 문제는 여러가지 정렬 알고리즘으로 풀 수 있다.

총 3가지 방식으로 풀어볼 것이다.

🔑 풀이1 : sort() 메서드

  • 입력값 input을 배열의 크기 N과 정렬해야 할 배열 arr로 나눠준다.
  • sort() 메서드로 arr의 요소들을 a, b로 가져와 비교하여 오름차순으로 정렬하고, 이를 arr에 재할당해준다.
// input값 처리
const input = require('fs').readFileSync('/dev/stdin').toString().trim().split('\n').map(Number);
[N, ...arr] = input;

solution(arr);

function solution(arr) {
  arr = arr.sort((a,b) => a - b);
  console.log(arr.join('\n'));
}

 

다행히 시간 초과가 되지 않고 풀렸다.

 

 


🔑 풀이2 : 퀵 정렬

  • 입력값 input을 배열의 크기 N과 정렬해야 할 배열 arr로 나눠준다.
  • 퀵 정렬 함수인 quickSort()로 pivot 값(기준값)을 정해주고 배열의 값들을 비교해준다.
// input값 처리
const input = require('fs').readFileSync('/dev/stdin').toString().trim().split('\n').map(Number);
[N, ...arr] = input;

function quickSort(arr, left, right) {
  if (left >= right) {
    return;
  }
  // 기준점
  const mid = Math.floor((left + right) / 2);
  const pivot = arr[mid];
  const partition = divide(arr, left, right, pivot);

  quickSort(arr, left, partition - 1);
  quickSort(arr, partition, right);

  return arr;
}

function divide(arr, left, right, pivot) {
  while (left <= right) {
    while (arr[left] < pivot) {  // pivot과 비교
      left++;
    }
    while (arr[right] > pivot) {
      right--;
    }

    if (left <= right) {   // 왼쪽 값과 오른쪽 값을 바꾸기
      let tmp = arr[left];
      arr[left] = arr[right];
      arr[right] = tmp;
      left++;
      right--;
    }
  }
  return left;
}

console.log(quickSort(arr, 0, arr.length -1).join('\n'));

 

퀵 정렬로 풀 경우, 시간초과가 발생한다.

이는 input이 이미 정렬된 배열(내림차순)이기에 대부분의 값을 비교해줘야 하며, 평균 n번 정도의 비교가 이루어진다.

즉, 시간 복잡도가 O(n^2)로 가장 안 좋은 경우이기에 시간초과가 발생할 수밖에 없다.

 

퀵 정렬에 대한 더 자세한 설명은 아래 링크를 참고하길 바란다.

https://valueengine.tistory.com/11

 

[알고리즘] 퀵 정렬 (Quick Sort)

퀵 정렬 (Quick Sort) 1. 퀵 정렬이란? 퀵 정렬(quick sort) 역시 병합 정렬과 마찬가지로 어떤 문제를 2개의 작은 문제로 분리해 각각을 해결하는 분할 정복 알고리즘 중 하나다. 1-1) 차이점 병합 정렬 -

valueengine.tistory.com

 


🔑 풀이3 : 병합 정렬

  • 입력값 input을 배열의 크기 N과 정렬해야 할 배열 arr로 나눠준다.
  • 함수 mergeSort()로 크기가 1인 부분 배열로 쪼개준 다음, 각 부분 배열의 인덱스값들을 서로 비교하여 작은 값부터 빈 배열 result에 넣어 정렬해준다.
// input값 처리
const input = require('fs').readFileSync('/dev/stdin').toString().trim().split('\n').map(Number);
[N, ...arr] = input;

console.log(mergeSort(arr).join('\n'));

function merge(left, right) {
  const result = [];
  let [i, j] = [0, 0];

  while (i < left.length && j < right.length) {
    if (left[i] <= right[j]) {     // left와 right 요소끼리 비교
      result.push(left[i]);
      i++;
    } else {
      result.push(right[j]);
      j++;
    }
  }
  while (i < left.length) {
    result.push(left[i]);   // left에 남아있는 값을 추가
    i++;
  }
  while (j < right.length) {
    result.push(right[j]);  // right에 남아있는 값을 추가
    j++;
  }
  return result;
}

// 정렬되지 않은 배열 arr를 요소 1개만 가진 배열이 될 때까지 쪼개기
function mergeSort(arr) {
  if (arr.length < 2) {
    return arr;
  }
  const mid = Math.ceil(arr.length / 2);
  const left = mergeSort(arr.slice(0, mid));
  const right = mergeSort(arr.slice(mid, arr.length));

  return merge(left, right);
}

 

내림차순으로 정렬된 입력값을 받아 sort() 메서드에 비해 시간이 더 걸리긴 했지만, 시간 내 풀렸다.

 

 

병합 정렬에 대한 더 자세한 설명은 아래 링크를 참고하길 바란다.

https://valueengine.tistory.com/9

 

[알고리즘] 병합 정렬 (merge sort)

병합 정렬 (merge sort) 1. 병합 정렬이란? 병합 정렬(merge sort)은 어떤 문제를 2개의 작은 문제로 분리해 각각 해결한 다음, 이걸 모아서 원래 문제를 해결하는 분할 정복 알고리즘 중 하나다. 병합 정

valueengine.tistory.com

 


References

 

728x90
반응형

'Problem Solving > BOJ' 카테고리의 다른 글

[BOJ] 1427번 : 소트인사이드  (0) 2023.03.31
[BOJ] 1181번 : 단어 정렬  (0) 2023.03.30
[BOJ] 24060번 : 병합 정렬1  (0) 2023.03.25
[BOJ] 2164번 : 카드2 (자료구조)  (0) 2023.03.09
[BOJ] 10773번 : 제로  (0) 2023.03.04