[JavaScript] 백준 1715 카드 정렬하기 (JS)

SanE·2024년 2월 1일

Algorithm

목록 보기
34/127

카드 정렬하기

문제 설명


간략하게 문제는 다음과 같다.

  • 각 묶음의 카드의 수를 A, B라 하면 보통 두 묶음을 합쳐서 하나로 만드는 데에는 A+B 번의 비교를 해야 한다.

ex) 예를 들어 10장, 20장, 40장의 묶음이 있다면 10장과 20장을 합친 뒤, 합친 30장 묶음과 40장을 합친다면 (10 + 20) + (30 + 40) = 100번의 비교가 필요하다. 그러나 10장과 40장을 합친 뒤, 합친 50장 묶음과 20장을 합친다면 (10 + 40) + (50 + 20) = 120 번의 비교가 필요하므로 덜 효율적인 방법이다.

  • 입력으로 N 개의 카드가 첫줄, 그 뒤에는 카드 묶음의 크기가 주어진다.
  • 하나의 카드 묶음으로 만들 때 최소 몇번의 비교를 해야하는가.

풀이 과정


가장 작은 경우는 작은 묶음 2개를 골라서 지속 적으로 더하는 방법이 가장 적을 것이다.
그 이유는 A, B, C, D 뭉치가 있고 순서대로 카드를 합쳐 준다고 했을 때, +를 더해주는 횟수로 계산하면

A+B(A+B) + C(A+B+C)+ D
A++ ++ + +
B++ ++ + +
C++ +
D+

다음과 같기 때문에 A,B,C,D 는 작은 숫자 순으로 정렬되어야 한다.

따라서 위의 문제는 우선순위 큐(Priority Queue) 문제이고 풀이 과정은 다음과 같다.

  • 우선순위 큐(Priority Queue) PQ에 값을 모두 넣는다.
  • PQ에서 값을 두개씩 꺼내서 더한 후 그 값을result 변수에 넣는다.
  • answerresult를 더한 후 PQ에 다시 result 값을 넣는다.
  • 위의 과정을 PQ 에 한개의 변수만 들어있을 때까지 반복

우선순위 큐(Priority Queue) 구현에 대한 설명은 링크에서 참고

전체 코드

    let fs = require("fs");
    let input = fs.readFileSync("/dev/stdin").toString().trim().split("\n").map(Number);
    let N = input.shift();
    class MinHeap {
        constructor() {
            this.heap = [null];
        }

        insert(element) {
            let current = this.heap.length;

            while (current > 1) {
                const parent = Math.floor(current / 2);
                if (this.heap[parent] > element) {
                    this.heap[current] = this.heap[parent];
                    current = parent;
                }else break;
            }
            this.heap[current] = element;
        }

        remove() {
            let top = this.heap[1];
            if (this.heap.length > 2) {
                this.heap[1] = this.heap.pop();
                let current = 1;
                let leftChild = current * 2;
                let rightChild = current * 2 + 1;
                while (this.heap[leftChild]) {
                    let CompareChild = leftChild;
                    if (this.heap[rightChild] && this.heap[leftChild] > this.heap[rightChild]) {
                        CompareChild = rightChild;
                    }
                    if (this.heap[CompareChild] < this.heap[current]) {
                        const temp = this.heap[current];
                        this.heap[current] = this.heap[CompareChild];
                        this.heap[CompareChild] = temp;
                        current = CompareChild;
                    }else break;
                    leftChild = current * 2;
                    rightChild = current * 2 + 1;
                }
            }else if (this.heap.length === 2) {
                this.heap.pop();
            }else{
                return 0;
            }
            return top;
        }

        getSize() {
            return this.heap.length - 1;
        }

        getHeap() {
            return this.heap;
        }
    }

    const PQ = new MinHeap();
    for (const number of input) {
        PQ.insert(number);
    }
    let answer = 0;
    while (PQ.getSize()) {
        if (PQ.getSize() > 1){
            const first = PQ.remove();
            const second = PQ.remove();
            const result = first + second;
            answer += result;
            PQ.insert(result);
        }else break;
    }
	console.log(answer);

후기


최소힙의 응용 문제였다.
최근들어 최소힙과 우선순위 큐 문제를 집중적으로 풀고 있는데 이제 최소힙을 직접 구현하는 것도 조금씩 익숙해 지는 것 같다.

profile
JavaScript를 사용하는 모두를 위해...

0개의 댓글