티스토리 뷰


문제 요약
- Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들 예정이다.
- 가장 맵지 않은 두 개의 음식을 섞어 새로운 음식을 만든다.
과정을 반복해 모든 음식의 스코빌 지수가 K 이상이 되도록 만든다.
최소 몇 번을 섞어야하는가?
자료구조 선택
최소값 또는 최대값을 찾아내야 하는 문제다.
가장 맵지 않은 두 개의 음식을 빠르게 찾아내야 하기 때문에
가장 적합한 자료구조로 최소 힙을 선택하였다.
최소 힙은 루트 노드가 항상 최솟값을 가진다.
문제 해결 과정
1. 스코빌 지수 배열을 최소 힙으로 변환한다.
이 과정 이후, 배열에서 가장 작은 값을 빠르게 찾을 수 있다.
2. 반복문
- 힙에서 가장 맵지 않은 음식을 꺼냄
- 두 번째로 맵지 않은 음식을 꺼냄
- 새로운 스코빌 지수 계산
- 새로운 음식을 힙에 넣음
- 모든 음식이 스코빌 지수 K가 넘을 때까지 반복
3. 힙의 최솟값이 K 이상이면 종료
function solution(scoville, K) {
scoville.sort((a, b) => a - b);
let mixCount = 0;
while (scoville[0] < K) {
if (scoville.length < 2) {
return -1;
}
const first = scoville.shift();
const second = scoville.shift();
const newScoville = first + (second * 2);
scoville.push(newScoville);
scoville.sort((a, b) => a - b);
mixCount += 1;
}
return mixCount;
}
힙 (최소 힙, 최대 힙)
힙(Heap)이란? 최댓값, 최솟값을 빠르게 찾기 위해 고안된 자료형으로 우선순위 큐를 위해 만들어졌다. 완전 이진 트리의 일종으로, 각 노드의 키값이 그 자식의 키 값보다 작지않거나(최대 힙),
velog.io
문제는 이 코드가 모두 효율성 테스트를 통과하지 못했다는 점이다.

뭐가 문제일까?
2단계 문제의 장벽이 너무 높다.
사용자의 코드에서 주의할 점은 sort 함수의 사용입니다.
sort 함수는 효율성이 낮아서, 음식을 매번 섞을 때마다 배열 전체를 정렬하면 시간 복잡도가 높아집니다. 대신 이 문제는 '힙(Heap)' 자료구조를 사용하면 더 효율적으로 해결할 수 있습니다. JavaScript에서는 기본적으로 힙 자료구조를 제공하지 않지만, 우선순위 큐를 직접 구현하거나 외부 라이브러리를 활용하여 힙과 유사한 기능을 구현할 수 있습니다. 문제의 키 포인트는 항상 스코빌 지수가 가장 낮은 두 개의 음식을 찾아야 한다는 것인데, 이를 힙을 활용해서 구현하면 매번 전체를 정렬할 필요 없이 효율적으로 두 최소값을 찾을 수 있습니다. 따라서 힙을 사용해 해결 방법을 고민해 보세요.
이런 대답을 얻었기 때문에,
그냥 코드의 수가 증가하더라도 직접 우선순위 큐를 구현해보았다.
[JS] 우선순위 큐 (Priority Queue)
velog.io
class MinHeap {
constructor() {
this.heap = [];
}
getParentIndex(index) {
return Math.floor((index - 1) / 2);
}
getLeftChildIndex(index) {
return index * 2 + 1;
}
getRightChildIndex(index) {
return index * 2 + 2;
}
swap(index1, index2) {
[this.heap[index1], this.heap[index2]] = [this.heap[index2], this.heap[index1]];
}
push(value) {
this.heap.push(value);
this.heapifyUp();
}
heapifyUp() {
let index = this.heap.length - 1;
while (this.getParentIndex(index) >= 0 && this.heap[this.getParentIndex(index)] > this.heap[index]) {
this.swap(this.getParentIndex(index), index);
index = this.getParentIndex(index);
}
}
pop() {
if (this.heap.length === 1) return this.heap.pop();
const root = this.heap[0];
this.heap[0] = this.heap.pop();
this.heapifyDown(0);
return root;
}
heapifyDown(index) {
let smallest = index;
const leftChild = this.getLeftChildIndex(index);
const rightChild = this.getRightChildIndex(index);
if (leftChild < this.heap.length && this.heap[leftChild] < this.heap[smallest]) {
smallest = leftChild;
}
if (rightChild < this.heap.length && this.heap[rightChild] < this.heap[smallest]) {
smallest = rightChild;
}
if (smallest !== index) {
this.swap(index, smallest);
this.heapifyDown(smallest);
}
}
peek() {
return this.heap[0];
}
size() {
return this.heap.length;
}
}
function solution(scoville, K) {
const minHeap = new MinHeap();
for (let num of scoville) {
minHeap.push(num);
}
let mixCount = 0;
while (minHeap.peek() < K) {
if (minHeap.size() < 2) {
return -1;
}
const first = minHeap.pop();
const second = minHeap.pop();
const newScoville = first + (second * 2);
minHeap.push(newScoville);
mixCount += 1;
}
return mixCount;
}
통과할 수 있었다...ㅎ
자바스크립트는 따로 제공되는 힙 클래스가 없기 때문에
직접 구현하거나 라이브러리를 사용해야한다.
시험 환경이 어떠할지 알 수 없기 때문에, 따로 힙 클래스를 구현해보았다.
'Oops, All Code! > 🤯 Oops, My Algorithm!' 카테고리의 다른 글
| ꒰ྀི 03. 프로그래머스:: 구명보트 (0) | 2024.07.16 |
|---|---|
| ꒰ྀི 02. 프로그래머스:: 주식가격 (0) | 2024.07.15 |
| ♡̈ 19. 프로그래머스:: 내적 (0) | 2024.07.13 |
| ♡̈ 18. 프로그래머스:: 행렬의 덧셈 (2) | 2024.07.13 |
| ♡̈ 17. 프로그래머스:: 최대공약수와 최소공배수 (0) | 2024.07.13 |
- Total
- Today
- Yesterday
- 프론트엔드
- 소사벌
- 우아한테크코스
- 코딩테스트
- 책추천
- 대학생팝업스토어
- 비즈플리마켓
- 네이버부스트캠프
- 회고
- 서평
- 대학생플리마켓
- 카드뉴스
- 안성스타필드
- js
- 경험플리마켓
- 도서추천
- 일급객체
- 카페추천
- 프리코스
- javascript
- 프로토타입
- 트러블슈팅
- typescript
- 소사벌맛집
- 부스트캠프
- 어른의어휘공부
- react
- 어휘력
- 도서리뷰
- 웹풀스택
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |