[Algorithm] 더 맵게
공부

[Algorithm] 더 맵게

작성일: 2023년 11월 02일

문제설명

더 맵게는 작은 순으로 정렬된 매운 음식들의 스코빌 지수가 K보다 작을 때 가장 작은 음식 2개를 섞어 K 이상으로 만든 후 섞은 횟수를 반환하는 문제이다.

문제해결

{
  "object": "block",
  "id": "72680286-67b1-42ed-abf4-8c4256eb766a",
  "parent": {
    "type": "page_id",
    "page_id": "390765fe-8b67-81c7-917c-ca716d9329cd"
  },
  "created_time": "2026-07-01T14:50:00.000Z",
  "last_edited_time": "2026-07-01T14:50:00.000Z",
  "created_by": {
    "object": "user",
    "id": "2ecd872b-594c-81f7-92e3-000210a8d473"
  },
  "last_edited_by": {
    "object": "user",
    "id": "2ecd872b-594c-81f7-92e3-000210a8d473"
  },
  "has_children": false,
  "in_trash": false,
  "type": "heading_4",
  "heading_4": {
    "rich_text": [
      {
        "type": "text",
        "text": {
          "content": "1차: 정렬 & Queue",
          "link": null
        },
        "annotations": {
          "bold": false,
          "italic": false,
          "strikethrough": false,
          "underline": false,
          "code": false,
          "color": "default"
        },
        "plain_text": "1차: 정렬 & Queue",
        "href": null
      }
    ],
    "is_toggleable": false,
    "color": "default"
  },
  "archived": false
}

Queue 배열에서 가장 작은 요소 2개를 꺼내 mix(Queue[0] + Queue[1] * 2)한 후 push하고 queue를 모두 검사하기 전 mix와 K 이상이면 count를 반환하는 방식으로 접근했다. 결과는 효율성 테스트 실패

function solution(scoville, K) {
  let count = 0;
  const queue = [];

  for (const s of scoville) {
    queue.push(s);
  }

  queue.sort((a, b) => a - b);
  while (queue.length - 1) {
    const first = queue.shift();
    const second = queue.shift();
    const mixed = first + second * 2;
    queue.push(mixed);
    queue.sort((a, b) => a - b);
    count++;

    if (queue[0] >= K) return count;
  }
  return queue[0] >= K ? count : -1;
}
{
  "object": "block",
  "id": "aec20250-b985-4cde-ac74-70aa49f50f89",
  "parent": {
    "type": "page_id",
    "page_id": "390765fe-8b67-81c7-917c-ca716d9329cd"
  },
  "created_time": "2026-07-01T14:50:00.000Z",
  "last_edited_time": "2026-07-01T14:50:00.000Z",
  "created_by": {
    "object": "user",
    "id": "2ecd872b-594c-81f7-92e3-000210a8d473"
  },
  "last_edited_by": {
    "object": "user",
    "id": "2ecd872b-594c-81f7-92e3-000210a8d473"
  },
  "has_children": false,
  "in_trash": false,
  "type": "heading_4",
  "heading_4": {
    "rich_text": [
      {
        "type": "text",
        "text": {
          "content": "2차: Class로 Heap 구현",
          "link": null
        },
        "annotations": {
          "bold": false,
          "italic": false,
          "strikethrough": false,
          "underline": false,
          "code": false,
          "color": "default"
        },
        "plain_text": "2차: Class로 Heap 구현",
        "href": null
      }
    ],
    "is_toggleable": false,
    "color": "default"
  },
  "archived": false
}
### Heap
  • Heap은 이진트리를 그리며 부모노드가 자식보다 작거나 같은 경우를 만들어 내는 자료 구조이다.
  • 자바는 메서드로 구현되어 있는데 자바스크립트는 없어서 직접 만들어야 한다.
  • class MinHeap {
      constructor() {
        this.heap = [];
      }
    
      size() {
        return this.heap.length;
      }
        
      push(value) {
        this.heap.push(value);
        let idx = this.heap.length - 1;
    
        while (
          idx > 0 &&
          this.heap[idx] < this.heap[Math.floor((idx - 1) / 2)]
        ) {
          const temp = this.heap[idx];
          this.heap[idx] = this.heap[Math.floor((idx - 1) / 2)];
          this.heap[Math.floor((idx - 1) / 2)] = temp;
          idx = Math.floor((idx - 1) / 2);
        }
      }
    
        // 값을 빼되, 오름차 순 정렬 함
      pop() {
        if (this.heap.length === 0) return null;
        if (this.heap.length === 1) return this.heap.pop();
    
        const minValue = this.heap[0];
        this.heap[0] = this.heap.pop();
        let idx = 0;
    
        while (idx * 2 + 1 < this.heap.length) {
          let minIdx = idx * 2 + 2 < this.heap.length && this.heap[idx * 2 + 2] < this.heap[idx * 2 + 1] ? idx * 2 + 2 : idx * 2 + 1;
    
          if (this.heap[idx] < this.heap[minIdx]) {
            break;
          }
    
          const temp = this.heap[idx];
          this.heap[idx] = this.heap[minIdx];
          this.heap[minIdx] = temp;
          idx = minIdx;
        }
    
        return minValue;
      }
    
      peek() {
        return this.heap[0];
      }
    }
    
    function solution(scoville, K) {
      const minHeap = new MinHeap();
    
      for (const v of scoville) {
        minHeap.push(v);
      }
    
      let count = 0;
    
      while (minHeap.size() >= 2 && minHeap.peek() < K) {
        const first = minHeap.pop();
        const second = minHeap.pop();
        const mixed = first + second * 2;
        minHeap.push(mixed);
        count++;
      }
    
      return minHeap.peek() >= K ? count : -1;
    }

    push, pop, peek 메서드의 시간 복잡도는 모두 O(log N)으로 전체 시간 복잡도는 O(N log N)으로 앞서 구현한 코드의 시간복잡도 O(N^2 log N)보다 빠르다.