[프로그래머스] 이중우선순위큐
class SymmetricMinMaxHeap {
constructor() {
this.heap = [null]
}
treeView() {
console.log('\n=TREE=')
console.log(`tree length: ${this.size()}`)
console.log(...this.heap.slice(0, 1))
console.log(...this.heap.slice(1, 3))
console.log(...this.heap.slice(3, 7))
console.log(...this.heap.slice(7, 15))
console.log(...this.heap.slice(15, 31))
}
size() {
return this.heap.length
}
insert(value) {
this.heap.push(value)
this.bubbleUp()
}
bubbleUp() {
let currentIndex
let isLeftNode
let siblingIndex
let parentIndex
let parentIsLeftNode
let parentSiblingIndex
const reloadVariables = (newIndex) => {
currentIndex = newIndex
isLeftNode = currentIndex % 2 === 1
siblingIndex = isLeftNode ? currentIndex + 1 : currentIndex - 1
parentIndex = Math.floor((currentIndex - 1) / 2)
parentIsLeftNode = parentIndex % 2 === 1
parentSiblingIndex = parentIsLeftNode
? parentIndex + 1
: parentIndex - 1
}
reloadVariables(this.heap.length - 1)
while (currentIndex > 0) {
if (this.heap[siblingIndex] !== undefined) {
if (isLeftNode) {
if (this.heap[currentIndex] > this.heap[siblingIndex]) {
;[this.heap[currentIndex], this.heap[siblingIndex]] = [
this.heap[siblingIndex],
this.heap[currentIndex],
]
reloadVariables(siblingIndex)
continue
}
}
else {
if (this.heap[currentIndex] < this.heap[siblingIndex]) {
;[this.heap[currentIndex], this.heap[siblingIndex]] = [
this.heap[siblingIndex],
this.heap[currentIndex],
]
reloadVariables(siblingIndex)
continue
}
}
}
if (parentIndex === 0) break
if (parentIsLeftNode) {
if (this.heap[currentIndex] < this.heap[parentIndex]) {
;[this.heap[currentIndex], this.heap[parentIndex]] = [
this.heap[parentIndex],
this.heap[currentIndex],
]
reloadVariables(parentIndex)
continue
}
if (this.heap[currentIndex] > this.heap[parentSiblingIndex]) {
;[this.heap[currentIndex], this.heap[parentSiblingIndex]] =
[this.heap[parentSiblingIndex], this.heap[currentIndex]]
reloadVariables(parentSiblingIndex)
continue
}
}
else {
if (this.heap[currentIndex] > this.heap[parentIndex]) {
;[this.heap[currentIndex], this.heap[parentIndex]] = [
this.heap[parentIndex],
this.heap[currentIndex],
]
reloadVariables(parentIndex)
continue
}
if (this.heap[currentIndex] < this.heap[parentSiblingIndex]) {
;[this.heap[currentIndex], this.heap[parentSiblingIndex]] =
[this.heap[parentSiblingIndex], this.heap[currentIndex]]
reloadVariables(parentSiblingIndex)
continue
}
}
break
}
}
extractMin() {
const min = this.heap[1]
if (this.size() <= 1) {
return null
} else if (this.size() <= 2) {
this.heap.pop()
} else {
this.heap[1] = this.heap.pop()
this.bubbleDown(1)
}
return min
}
extractMax() {
let max = this.heap[2]
if (this.size() <= 1) {
return null
} else if (this.size() <= 2) {
max = this.heap[1]
this.heap.pop()
} else if (this.size() <= 3) {
this.heap.pop()
} else {
this.heap[2] = this.heap.pop()
this.bubbleDown(2)
}
return max
}
bubbleDown(index) {
const isLeftNode = index % 2 === 1
const leftChildIndex = 2 * index + 1
const rightChildIndex = 2 * index + 2
const siblingIndex = isLeftNode ? index + 1 : index - 1
const siblingLeftChildIndex = 2 * siblingIndex + 1
const siblingRightChildIndex = 2 * siblingIndex + 2
const length = this.heap.length
let toBeExchangeIndex = index
if (isLeftNode) {
if (
leftChildIndex < length &&
this.heap[leftChildIndex] < this.heap[toBeExchangeIndex]
) {
toBeExchangeIndex = leftChildIndex
}
if (
rightChildIndex < length &&
this.heap[rightChildIndex] < this.heap[toBeExchangeIndex]
) {
toBeExchangeIndex = rightChildIndex
}
if (
siblingLeftChildIndex < length &&
this.heap[siblingLeftChildIndex] < this.heap[toBeExchangeIndex]
) {
toBeExchangeIndex = siblingLeftChildIndex
}
if (
siblingRightChildIndex < length &&
this.heap[siblingRightChildIndex] < this.heap[toBeExchangeIndex]
) {
toBeExchangeIndex = siblingRightChildIndex
}
if (toBeExchangeIndex !== index) {
;[this.heap[index], this.heap[toBeExchangeIndex]] = [
this.heap[toBeExchangeIndex],
this.heap[index],
]
this.bubbleDown(toBeExchangeIndex)
}
}
else {
if (
leftChildIndex < length &&
this.heap[leftChildIndex] > this.heap[toBeExchangeIndex]
) {
toBeExchangeIndex = leftChildIndex
}
if (
rightChildIndex < length &&
this.heap[rightChildIndex] > this.heap[toBeExchangeIndex]
) {
toBeExchangeIndex = rightChildIndex
}
if (
siblingLeftChildIndex < length &&
this.heap[siblingLeftChildIndex] > this.heap[toBeExchangeIndex]
) {
toBeExchangeIndex = siblingLeftChildIndex
}
if (
siblingRightChildIndex < length &&
this.heap[siblingRightChildIndex] > this.heap[toBeExchangeIndex]
) {
toBeExchangeIndex = siblingRightChildIndex
}
if (toBeExchangeIndex !== index) {
;[this.heap[index], this.heap[toBeExchangeIndex]] = [
this.heap[toBeExchangeIndex],
this.heap[index],
]
this.bubbleDown(toBeExchangeIndex)
}
}
}
}
const solution = (operations) => {
const Heap = new SymmetricMinMaxHeap()
for (let operation of operations) {
operation[0] === 'I'
? Heap.insert(+operation.slice(2))
: operation.slice(2) === '1'
? Heap.extractMax()
: Heap.extractMin()
}
if (Heap.size() <= 1) {
return [0, 0]
} else if (Heap.size() === 2) {
const data = Heap.extractMin()
return [data, data]
} else {
return [Heap.extractMax(), Heap.extractMin()]
}
}