Skip to content

Instantly share code, notes, and snippets.

@Shaddyjr
Created October 13, 2019 01:56
Show Gist options
  • Save Shaddyjr/3ae4edd88953fc43aae623cd8dd73c3c to your computer and use it in GitHub Desktop.
Save Shaddyjr/3ae4edd88953fc43aae623cd8dd73c3c to your computer and use it in GitHub Desktop.
HackerRank "Find the Running Median"
class Heap{
constructor(){
this.array = new Array(50000);
this.length = 0;
}
guardEmpty(){
if(this.length === 0) throw Error("Heap is Empty");
}
getValue(index){
const item = this.array[index];
return this.valueProperty ? item[this.valueProperty] : item;
}
peek(){
this.guardEmpty();
return this.getValue(0);
}
getParentIndex(childIndex){ // returns raw array index
if(childIndex<=0) return 0;
return Math.floor((childIndex + 1) / 2) - 1;
}
getChildIndex(parentIndex, right = false){ // returns raw array index
const leftChildIndex = (((parentIndex + 1) * 2) - 1) + right;
if(this.getValue(leftChildIndex) === undefined) return -1; // out of index range
return leftChildIndex;
}
getRightChildIndex(parentIndex){
return this.getChildIndex(parentIndex, true);
}
getLeftChildIndex(parentIndex){
return this.getChildIndex(parentIndex);
}
insert(item){
this.array[this.length++] = item;
this.bubbleUp(this.length - 1);
}
removeTop(){
this.guardEmpty();
const out = this.peek();
if(this.array.length === 1){
this.array[--this.length] = undefined;
return out;
}
this.array[0] = this.array[--this.length];
this.bubbleDown(0);
return out;
}
swap(i, j){
const temp = this.array[i];
this.array[i] = this.array[j];
this.array[j] = temp;
}
bubbleUp(index){
// get target val
// get parent index
// get parent val
// if parent - child relationship is wrong
// swap parent - child and call bubbleUp on parent
if(index <= 0) return;
const targetVal = this.getValue(index);
const parentIndex = this.getParentIndex(index);
const parentVal = this.getValue(parentIndex);
if(!this.isCorrectParentChildRelationship(parentVal, targetVal)){
this.swap(parentIndex, index);
this.bubbleUp(parentIndex);
}
}
bubbleDown(parentIndex){
// index assumed to be parent that may
// may not be in appropriate parent - child relation
// get value
// if left is incorrect relationship, swap and call bubbleDown on child
// reassign parent val to new val
// if right is incorrect relationship, swap and call bubbleDown on child
let parentVal = this.getValue(parentIndex);
const leftIndex = this.getLeftChildIndex(parentIndex);
const rightIndex = this.getRightChildIndex(parentIndex);
if(leftIndex > 0){
const leftVal = this.getValue(leftIndex);
if(!this.isCorrectParentChildRelationship(parentVal, leftVal)){
this.swap(parentIndex, leftIndex);
this.bubbleDown(leftIndex);
parentVal = leftVal;
}
}
if(rightIndex >=0){
const rightVal = this.getValue(rightIndex);
if(!this.isCorrectParentChildRelationship(parentVal, rightVal)){
this.swap(parentIndex, rightIndex);
this.bubbleDown(rightIndex);
}
}
}
isCorrectParentChildRelationship(parentVal, childVal){
}
}
class MaxHeap extends Heap{
constructor(valueProperty){
super(valueProperty);
}
isCorrectParentChildRelationship(parentVal, childVal){
return childVal < parentVal;
}
}
class MinHeap extends Heap{
constructor(valueProperty){
super(valueProperty);
}
isCorrectParentChildRelationship(parentVal, childVal){
return parentVal < childVal;
}
}
class MedianHeap{
constructor(){
this.minHeap = new MinHeap;
this.maxHeap = new MaxHeap;
}
insert(val){
const maxL = this.maxHeap.length;
const minL = this.minHeap.length;
if(maxL === 0){
this.maxHeap.insert(val);
return;
}
// if heaps are same
if(maxL === minL){
if(val < this.minHeap.peek()){
this.maxHeap.insert(val);
}else{
this.minHeap.insert(val);
this.maxHeap.insert(this.minHeap.removeTop());
}
}else if(maxL > minL){
if(val > this.maxHeap.peek()){
this.minHeap.insert(val);
}else{
this.maxHeap.insert(val);
this.minHeap.insert(this.maxHeap.removeTop());
}
} // maxHeap always larger than min heap (no need for else)
}
avg(a,b){
return (a + b) / 2;
}
getMedian(){
if(this.maxHeap.length > this.minHeap.length){
return this.maxHeap.peek();
}
return this.avg(this.maxHeap.peek(), this.minHeap.peek());
}
}
function formatNum(num){
return num.toFixed(1);
}
function runningMedian(arr) {
const medianHeap = new MedianHeap();
for(let i = 0;i < arr.length; i++){
medianHeap.insert(arr[i]);
arr[i] = formatNum(medianHeap.getMedian());
}
return arr;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment