Coding Interview

3-14. [스택, 큐] 절댓값 힙

milliwonkim 2023. 1. 28. 19:47
반응형
SMALL

절댓값 힙

시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 (추가 시간 없음) (하단 참고) 256 MB 33723 18725 15236 56.392%

문제

절댓값 힙은 다음과 같은 연산을 지원하는 자료구조이다.

  1. 배열에 정수 x (x ≠ 0)를 넣는다.
  2. 배열에서 절댓값이 가장 작은 값을 출력하고, 그 값을 배열에서 제거한다. 절댓값이 가장 작은 값이 여러개일 때는, 가장 작은 수를 출력하고, 그 값을 배열에서 제거한다.

프로그램은 처음에 비어있는 배열에서 시작하게 된다.

입력

첫째 줄에 연산의 개수 N(1≤N≤100,000)이 주어진다. 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 만약 x가 0이 아니라면 배열에 x라는 값을 넣는(추가하는) 연산이고, x가 0이라면 배열에서 절댓값이 가장 작은 값을 출력하고 그 값을 배열에서 제거하는 경우이다. 입력되는 정수는 -231보다 크고, 231보다 작다.

출력

입력에서 0이 주어진 회수만큼 답을 출력한다. 만약 배열이 비어 있는 경우인데 절댓값이 가장 작은 값을 출력하라고 한 경우에는 0을 출력하면 된다.

예제 입력 1 복사

18
1
-1
0
0
0
1
1
-1
-1
2
-2
0
0
0
0
0
0
0

예제 출력 1 복사

-1
1
0
-1
-1
1
1
-2
2
0

출처

시간 제한

  • Java 8: 2 초
  • Java 8 (OpenJDK): 2 초
  • Java 11: 2 초
  • Kotlin (JVM): 2 초

풀이

- minHeap으로 푼다

이유: 절댓값이 같을 때 음수를 우선 출력해야함

 

 

코드

class AbsoluteMinHeap {
  constructor() {
    this.heap = [];
  }

  empty() {
    if (this.heap.length == 0) {
      return true;
    }
    return false;
  }

  swap(arr, x, y) {
    let temp = arr[x];
    arr[x] = arr[y];
    arr[y] = temp;
    return;
  }

  //[절대값, 원래값]으로 넣어줄 에정.

  insert(value) {
    this.heap.push(value);
    this.bubbleUp();
  }

  bubbleUp() {
    let currentIndex = this.heap.length - 1;

    while (currentIndex > 0) {
      const parentIndex = Math.floor((currentIndex - 1) / 2);
      if (
        this.heap[parentIndex][0] < this.heap[currentIndex][0] ||
        (this.heap[parentIndex][0] == this.heap[currentIndex][0] &&
          this.heap[parentIndex][1] < this.heap[currentIndex][1])
      ) {
        break;
      }
      this.swap(this.heap, parentIndex, currentIndex);
      currentIndex = parentIndex;
    }
  }

  extractMin() {
    if (this.heap.length == 1) {
      return this.heap.pop();
    }
    const min = this.heap[0];
    this.heap[0] = this.heap.pop();
    this.sinkDown(0);
    return min;
  }

  sinkDown(index) {
    const leftIndex = 2 * index + 1;
    const rightIndex = 2 * index + 2;
    const length = this.heap.length;
    let smallestIndex = index;

    if (
      leftIndex < length &&
      (this.heap[leftIndex][0] < this.heap[smallestIndex][0] ||
        (this.heap[leftIndex][0] == this.heap[smallestIndex][0] &&
          this.heap[leftIndex][1] < this.heap[smallestIndex][1]))
    ) {
      smallestIndex = leftIndex;
    }
    if (
      rightIndex < length &&
      (this.heap[rightIndex][0] < this.heap[smallestIndex][0] ||
        (this.heap[rightIndex][0] == this.heap[smallestIndex][0] &&
          this.heap[rightIndex][1] < this.heap[smallestIndex][1]))
    ) {
      smallestIndex = rightIndex;
    }
    if (smallestIndex !== index) {
      this.swap(this.heap, index, smallestIndex);
      this.sinkDown(smallestIndex);
    }
  }
}

const N = 18;
const list = [1, -1, 0, 0, 0, 1, 1, -1, -1, 2, -2, 0, 0, 0, 0, 0, 0, 0];

const queue = new AbsoluteMinHeap();
const answer = [];

for (let i = 0; i < list.length; i++) {
  if (list[i] === 0) {
    if (queue.empty()) {
      answer.push(0);
    } else {
      let temp = queue.extractMin();
      console.log("TEMP", temp[1]);
      if (temp) {
        answer.push(temp[1]);
      } else {
        answer.push(0);
      }
    }
  } else {
    queue.insert([Math.abs(list[i]), list[i]]);
  }

  console.log("QUEUE: ", queue);
  console.log("ANSWER: ", answer);
  console.log("------------");
}

 

참고

https://juhee-maeng.tistory.com/94

 

[자료구조] 힙(Heap)이란? 최대힙(Max Heap)과 최소힙(Min Heap)

힙(Heap) 최대 힙(Max Heap) 최소 힙(Min Heap) 1. 최대 힙(Max Heap) 최대 트리(Max Tree)는 각 노드의 키(Key)값이 (자식 노드가 있다면) 그 자식의 키(Key)값보다 작지 않은(=크거나 같은) 트리이다. 최대 힙(Max H

juhee-maeng.tistory.com

 

반응형
LIST