Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Heaps #156

Merged
merged 16 commits into from
Nov 5, 2019
Merged

Heaps #156

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .assets/dsa.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<img src=".assets/logo.png" align="right"/>

# Problem Solving using Javascript

[![Open Source Love](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/vinitshahdeo/HacktoberFest)
Expand All @@ -7,17 +9,20 @@

Collection of interview questions with Unit Tests. Problems includes Data Structures, Logical and few Classical problems.

## Table of Contents
![DSA](.assets/dsa.jpeg)

## Overview

This repo contains the following sections implemented in **JavaScript**

This repo contains the following in **JavaScript**
- Data Structures
- Algorithms
- Logical Problems
- Classics (Few of the classical questions)
- [Data Structures](src/_DataStructures_)
- [Algorithms](src/_Algorithms_)
- [Logical Problems](src/_Problems_)
- [Classics (Few of the classical questions)](src/_Classics_)

Find the detailed Table of Contents here: [Detailed TOC](TOC.md)
Find the detailed contents and problem list here: [Table Of Contents](TOC.md)

## CONTRIBUTION Guide
## Contribution Guide

It's great to know that you want to contribute to this repo. Thanks for taking interest. please fing the [guide here](https://github.com/knaxus/problem-solving-javascript/blob/master/CONTRIBUTING.md)

Expand Down
10 changes: 7 additions & 3 deletions TOC.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

## Table of Contents

### Data Structures
Expand Down Expand Up @@ -44,6 +43,12 @@
- [Unique words count in a Trie](src/_DataStructures_/Trees/Trie/unique-word-count)
- [All the words from a Trie](src/_DataStructures_/Trees/Trie/all-words-in-trie)
- [Unique words in a Trie](src/_DataStructures_/Trees/Trie/get-unique-words)
- [Heaps](src/_DataStructures_/Heaps)
- [MaxHeap](src/_DataStructures_/Heaps/MaxHeap)
- [MinHeap](src/_DataStructures_/Heaps/MinHeap)
- Problems
- [K Largest Elements](src/_DataStructures_/Heaps/k-largest-in-array)
- [K Smallest Elements](src/_DataStructures_/Heaps/k-smallest-in-array)

### Logical Problems

Expand Down Expand Up @@ -75,8 +80,7 @@

- [LRU Cache](src/_Algorithms_/lru-cache)
- Path Finders
- [A*](src/_Algorithms_/path-finder/a-star)

- [A\*](src/_Algorithms_/path-finder/a-star)

### Classics

Expand Down
9 changes: 9 additions & 0 deletions src/_DataStructures_/Heaps/MaxHeap/MaxHeap.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ describe('MaxHeap', () => {
expect(mh instanceof MaxHeap).toEqual(true);
});

it('Should create a MaxHeap using collection', () => {
const mHBulk = new MaxHeap([1, 3, 21, 9, 101, 0]);
expect(mHBulk.getMax()).toEqual(101);
});

it('Should add an element to the MaxHeap', () => {
mh.add(10);
expect(mh.getMax()).toEqual(10);
Expand Down Expand Up @@ -47,4 +52,8 @@ describe('MaxHeap', () => {
expect(mh.remove()).toEqual(1);
expect(mh.getMax()).toEqual(null);
});

it('Should return `null` on `remove() called on empty heap`', () => {
expect(mh.getMax()).toEqual(null);
});
});
24 changes: 13 additions & 11 deletions src/_DataStructures_/Heaps/MaxHeap/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
class MaxHeap {
constructor() {
constructor(collection) {
this.heap = [];
if (collection) {
collection.forEach((element) => {
this.add(element);
});
}
}

add(element) {
Expand All @@ -11,27 +16,24 @@ class MaxHeap {
}

getMax() {
return this.heap[0] || null;
return this.heap[0] !== undefined ? this.heap[0] : null;
}

remove() {
const max = this.heap[0] !== undefined ? this.heap[0] : null;
// return the element at the root
const max = this.heap[0] || null;
if (this.heap.length === 1) {
this.heap.pop();
}

if (this.heap.length > 1) {
// move the leaf to the root
this.heap[0] = this.heap[this.heap.length - 1];
this.heap.splice(this.heap.length - 1, 1);
this.heap.pop();
// restore the heapify property
// eslint-disable-next-line no-underscore-dangle
this.__heapify(0);
return max;
}

if (this.heap.length === 1) {
this.heap.splice(this.heap.length - 1, 1);
return max;
}

return max;
}

Expand Down
59 changes: 59 additions & 0 deletions src/_DataStructures_/Heaps/MinHeap/MinHeap.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const MinHeap = require('.');

describe('MinHeap', () => {
it('Should be a class', () => {
expect(typeof MinHeap.prototype.constructor).toEqual('function');
});

const mh = new MinHeap();

beforeEach(() => {
mh.destroy();
});

it('Should create an instance of MinHeap', () => {
expect(mh instanceof MinHeap).toEqual(true);
});

it('Should create a MinHeap using collection', () => {
const mHBulk = new MinHeap([112, 3, 21, 9, 10, 0]);
expect(mHBulk.getMin()).toEqual(0);
});

it('Should add an element to the MinHeap', () => {
mh.add(10);
expect(mh.getMin()).toEqual(10);
});

it('Should keep the smallest element at the root', () => {
[12, 5, 34].forEach(el => mh.add(el));
expect(mh.getMin()).toEqual(5);
});

it('Should retain Heap properties after removal of an element', () => {
[12, 45, 1, 34].forEach(el => mh.add(el));
expect(mh.getMin()).toEqual(1);
mh.remove();
expect(mh.getMin()).toEqual(12);
});

it('Should return `null` when heap is empty', () => {
[1, 34].forEach(el => mh.add(el));
expect(mh.getMin()).toEqual(1);
mh.remove();
mh.remove();
expect(mh.getMin()).toEqual(null);
});

it('Should return the elelment value on `remove()`', () => {
[1, 34].forEach(el => mh.add(el));
expect(mh.getMin()).toEqual(1);
expect(mh.remove()).toEqual(1);
expect(mh.remove()).toEqual(34);
expect(mh.getMin()).toEqual(null);
});

it('Should return `null` on `remove() called on empty heap`', () => {
expect(mh.getMin()).toEqual(null);
});
});
78 changes: 78 additions & 0 deletions src/_DataStructures_/Heaps/MinHeap/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
class MinHeap {
constructor(collection) {
this.heap = [];

if (collection) {
collection.forEach((element) => {
this.add(element);
});
}
}

add(element) {
this.heap.push(element);
// check for the parent element & swap if required
// eslint-disable-next-line no-underscore-dangle
this.__traverseUpAndSwap(this.heap.length - 1);
}

getMin() {
return this.heap[0] !== undefined ? this.heap[0] : null;
}

remove() {
const min = this.heap[0] !== undefined ? this.heap[0] : null;
if (this.heap.length === 1) {
this.heap.pop();
}
if (this.heap.length > 1) {
this.heap[0] = this.heap[this.heap.length - 1];
this.heap.pop();
// eslint-disable-next-line no-underscore-dangle
this.__heapify(0);
}
return min;
}

destroy() {
this.heap = [];
}

// eslint-disable-next-line consistent-return
__traverseUpAndSwap(index) {
if (index <= 0) return null;

const parent = Math.floor(index / 2);

if (this.heap[parent] > this.heap[index]) {
const temp = this.heap[parent];
this.heap[parent] = this.heap[index];
this.heap[index] = temp;
// eslint-disable-next-line no-underscore-dangle
this.__traverseUpAndSwap(parent);
}
}

__heapify(index) {
const left = index * 2;
const right = index * 2 + 1;

let smallest = index;

if (this.heap.length > left && this.heap[smallest] > this.heap[left]) {
smallest = left;
}
if (this.heap.length > right && this.heap[smallest] > this.heap[right]) {
smallest = right;
}
if (smallest !== index) {
const tmp = this.heap[smallest];
this.heap[smallest] = this.heap[index];
this.heap[index] = tmp;
// eslint-disable-next-line no-underscore-dangle
this.__heapify(smallest);
}
}
}

module.exports = MinHeap;
22 changes: 22 additions & 0 deletions src/_DataStructures_/Heaps/k-largest-in-array/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const MaxHeap = require('../MaxHeap');

/**
* Find the 4 largest elements from an array
*/

function findKLargest(collection, k) {
if (!collection || !Array.isArray(collection)) {
throw new Error('Invalid / missing collection');
}

// create a MaxHeap using the collection
const mh = new MaxHeap(collection);
const result = [];

for (let i = 0; i < k; i += 1) {
result.push(mh.remove());
}
return result;
}

module.exports = findKLargest;
21 changes: 21 additions & 0 deletions src/_DataStructures_/Heaps/k-smallest-in-array/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Find 4 smallest elements in an array
*/

const MinHeap = require('../MinHeap');

function findKSmallest(collection, k) {
if (!collection || !Array.isArray(collection)) {
throw new Error('Invalid / missing collection');
}

// create a MinHeap using the collection
const mh = new MinHeap(collection);
const result = [];
for (let i = 0; i < k; i += 1) {
result.push(mh.remove());
}
return result;
}

module.exports = findKSmallest;