├── .gitignore ├── 5-hash-tables ├── javascript │ └── hash-tables.js └── php │ └── hash-tables.php ├── 4-quicksort ├── haskell │ └── quicksort.hs └── javascript │ ├── quicksort2.js │ └── quicksort1.js ├── 3-recursion ├── go │ └── recursion.go ├── javascript │ └── recursion.js └── php │ └── recursion.php ├── 1-introduction-to-algorithms ├── go │ └── binary-search.go ├── javascript │ └── binary-search.js └── php │ └── binary-search.php ├── extras └── recursive-binary-search │ ├── go │ └── recursive-binary-search.go │ ├── javascript │ └── recursive-binary-search.js │ └── php │ └── recursive-binary-search.php ├── 2-selection-sort ├── go │ └── selection-sort.go ├── php │ └── selection-sort.php └── javascript │ └── selection-sort.js ├── 6-breadth-first-search ├── php │ └── breadth-first-search.php └── javascript │ └── breadth-first-search.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ -------------------------------------------------------------------------------- /5-hash-tables/javascript/hash-tables.js: -------------------------------------------------------------------------------- 1 | let HashTable = {}; 2 | 3 | HashTable['Apple Cider'] = 2.99; 4 | HashTable['Orange Juice'] = 1.99; 5 | 6 | console.log(HashTable['Apple Cider']); // '2.99' 7 | console.log(HashTable['Orange Juice']); // '1.99' -------------------------------------------------------------------------------- /4-quicksort/haskell/quicksort.hs: -------------------------------------------------------------------------------- 1 | -- Quicksort implementation 2 | quicksort [] = [] 3 | quicksort (x : xs) = quicksort less ++ [x] ++ quicksort more 4 | where less = [a | a <- xs, a <= x] 5 | more = [b | b <- xs, b > x] 6 | -------------------------------------------------------------------------------- /3-recursion/go/recursion.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func factorial(num int) int { 8 | if num == 1 { 9 | return 1 10 | } 11 | 12 | return num * factorial(num - 1) 13 | } 14 | 15 | func main() { 16 | fmt.Println(factorial(5)); // 5 * 4 * 3 * 2 * 1 === 120 17 | } -------------------------------------------------------------------------------- /3-recursion/javascript/recursion.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the factorial of a number using recursion 3 | * 4 | * @param num 5 | */ 6 | function factorial(num) { 7 | if (num === 1) { 8 | return 1; 9 | } 10 | 11 | return num * factorial(num - 1); 12 | } 13 | 14 | console.log(factorial(5)); // 5 * 4 * 3 * 2 * 1 === 120 -------------------------------------------------------------------------------- /3-recursion/php/recursion.php: -------------------------------------------------------------------------------- 1 | 'Mistakes are always forgivable, if one has the courage to admit them.', 5 | 'Steve Jobs' => 'Innovation distinguishes between a leader and a follower.' 6 | ); 7 | 8 | echo $quotes['Bruce Lee']; // Mistakes are always forgivable, if one has the courage to admit them. 9 | echo $quotes['Steve Jobs']; // Innovation distinguishes between a leader and a follower. -------------------------------------------------------------------------------- /1-introduction-to-algorithms/go/binary-search.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | var list = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 8 | 9 | func binarySearch(list []int, val int) int { 10 | low := 0 11 | high := len(list) - 1 12 | 13 | for low <= high { 14 | mid := (low + high) / 2 15 | 16 | if list[mid] == val { 17 | return mid 18 | } else if list[mid] < val { 19 | low = mid + 1 20 | } else if list[mid] > val { 21 | high = mid - 1 22 | } 23 | 24 | mid = (low + high) / 2 25 | } 26 | 27 | return -1 28 | } 29 | 30 | func main() { 31 | fmt.Println(binarySearch(list, 1)) // 0 32 | fmt.Println(binarySearch(list, 11)) // -1, not found 33 | } 34 | -------------------------------------------------------------------------------- /extras/recursive-binary-search/go/recursive-binary-search.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func recursiveBinarySearch(list []int, val int, low int, high int) int { 8 | if low > high { 9 | return -1 10 | } 11 | 12 | mid := (low + high) / 2; 13 | 14 | if list[mid] == val { 15 | return mid 16 | } else if list[mid] > val { 17 | return recursiveBinarySearch(list, val, low, mid - 1) 18 | } else if list[mid] < val { 19 | return recursiveBinarySearch(list, val, mid + 1, high) 20 | } 21 | 22 | panic("This is never called") 23 | } 24 | 25 | func main() { 26 | list := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 27 | 28 | fmt.Println(recursiveBinarySearch(list, 4, 0, len(list))) // 3 29 | fmt.Println(recursiveBinarySearch(list, -5, 0, len(list))) // -1 30 | } -------------------------------------------------------------------------------- /1-introduction-to-algorithms/javascript/binary-search.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Find index of `val` in sorted `list` 3 | * 4 | * @param list 5 | * @param val 6 | * @returns {number} 7 | */ 8 | function binarySearch(list, val) { 9 | let low = 0, 10 | high = list.length - 1; 11 | 12 | while (low <= high) { 13 | let mid = Math.floor((low + high) / 2); 14 | 15 | if (list[mid] === val) { 16 | return mid; 17 | } else if (list[mid] < val) { 18 | low = mid + 1; 19 | } else if (list[mid] > val) { 20 | high = mid - 1; 21 | } 22 | } 23 | 24 | return -1; 25 | } 26 | 27 | let list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 28 | 29 | binarySearch(list, 11); // -1: 11 not in list 30 | binarySearch(list, 7); // 6: 7 found at index 6. -------------------------------------------------------------------------------- /1-introduction-to-algorithms/php/binary-search.php: -------------------------------------------------------------------------------- 1 | $val) { 20 | $high = $mid - 1; 21 | } else if ($list[$mid] < $val) { 22 | $low = $mid + 1; 23 | } 24 | } 25 | 26 | return -1; 27 | } 28 | 29 | $list = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); 30 | 31 | echo binarySearch($list, 7); // 6 32 | echo binarySearch($list, 16); // -1 -------------------------------------------------------------------------------- /extras/recursive-binary-search/javascript/recursive-binary-search.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Recursive binary search implementation 3 | * 4 | * @param list 5 | * @param val 6 | * @param low 7 | * @param high 8 | */ 9 | function recursiveBinarySearch(list, val, low, high) { 10 | if (low > high) { 11 | return -1; 12 | } 13 | 14 | let mid = Math.floor((low + high) / 2); 15 | 16 | if (list[mid] === val) { 17 | return mid; 18 | } else if (list[mid] > val) { 19 | return recursiveBinarySearch(list, val, low, mid -1); 20 | } else if (list[mid] < val) { 21 | return recursiveBinarySearch(list, val, mid + 1, high); 22 | } 23 | } 24 | 25 | let list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 26 | 27 | recursiveBinarySearch(list, 7, 0, list.length); // 6 28 | recursiveBinarySearch(list, 11, 0, list.length); // -1 -------------------------------------------------------------------------------- /extras/recursive-binary-search/php/recursive-binary-search.php: -------------------------------------------------------------------------------- 1 | $high) { 14 | return -1; 15 | } 16 | 17 | $mid = floor(($low + $high) / 2); 18 | 19 | if ($arr[$mid] == $val) { 20 | return $mid; 21 | } else if ($arr[$mid] > $val) { 22 | return recursiveBinarySearch($arr, $val, $low, $mid - 1); 23 | } else if ($arr[$mid] < $val) { 24 | return recursiveBinarySearch($arr, $val, $mid + 1, $high); 25 | } 26 | } 27 | 28 | $arr = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); 29 | 30 | echo recursiveBinarySearch($arr, 13, 0, count($arr)); // 12 -------------------------------------------------------------------------------- /2-selection-sort/go/selection-sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func findSmallest(arr []int) int { 8 | i := 1 9 | smallest := arr[0] 10 | length := len(arr) 11 | smallestIndex := 0 12 | 13 | for i < length { 14 | if arr[i] < smallest { 15 | smallest = arr[i] 16 | smallestIndex = i 17 | } 18 | i++ 19 | } 20 | 21 | return smallestIndex 22 | } 23 | 24 | func selectionSort(arr []int) []int { 25 | i := 0 26 | length := len(arr) 27 | newArr := []int{} 28 | 29 | for i < length { 30 | smallestIndex := findSmallest(arr) 31 | newArr = append(newArr, arr[smallestIndex]) 32 | arr = append(arr[:smallestIndex], arr[smallestIndex+1:]...) 33 | i++ 34 | } 35 | 36 | return newArr 37 | } 38 | 39 | func main() { 40 | list := []int{10, 6, 7, 5, 9, 8, 4, 2, 3, 1} 41 | 42 | fmt.Println(selectionSort(list)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 43 | } -------------------------------------------------------------------------------- /2-selection-sort/php/selection-sort.php: -------------------------------------------------------------------------------- 1 | 2 | pivot) { 21 | more.push(arr[i]); 22 | } else { 23 | less.push(arr[i]); 24 | } 25 | } 26 | } 27 | 28 | return sorted.concat(quicksort(less)).concat([pivot]).concat(quicksort(more)); 29 | } 30 | 31 | /** 32 | * Random number (min inclusive, max exclusive) 33 | * 34 | * @param min 35 | * @param max 36 | * @returns {*} 37 | */ 38 | function rand(min, max) { 39 | return Math.floor( Math.random() * (max - min) + min ); 40 | } 41 | 42 | let arr = [8, 4, 1, 10, 9, 7, 6, 2, 5, 3]; 43 | 44 | console.log(quicksort(arr)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -------------------------------------------------------------------------------- /4-quicksort/javascript/quicksort1.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Quicksort implementation, without creating new arrays 3 | * 4 | * @param items 5 | * @param left 6 | * @param right 7 | * @returns {*} 8 | */ 9 | function quicksort(items, left, right) { 10 | if (items.length > 1) { 11 | left = typeof left !== 'number' ? 0 : left; 12 | right = typeof right !== 'number' ? items.length - 1 : right; 13 | 14 | let index = partition(items, left, right); 15 | 16 | if (left < index - 1) { 17 | quicksort(items, left, index - 1); 18 | } 19 | 20 | if (index < right) { 21 | quicksort(items, index, right); 22 | } 23 | } 24 | 25 | return items; 26 | } 27 | 28 | function swap(items, firstIndex, secondIndex) { 29 | let temp = items[firstIndex]; 30 | items[firstIndex] = items[secondIndex]; 31 | items[secondIndex] = temp; 32 | } 33 | 34 | function partition(items, left, right) { 35 | let pivot = items[Math.floor((right + left) / 2)], 36 | i = left, 37 | y = right; 38 | 39 | while (i <= y) { 40 | while(items[i] < pivot) { 41 | i++; 42 | } 43 | 44 | while(items[y] > pivot) { 45 | y--; 46 | } 47 | 48 | if (i <= y) { 49 | swap(items, i, y); 50 | i++; 51 | y--; 52 | } 53 | } 54 | 55 | return i; 56 | } 57 | 58 | let arr = [10, 3, 7, 5, 9, 2, 8, 1, 6, 4]; 59 | 60 | console.log(quicksort(arr)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -------------------------------------------------------------------------------- /6-breadth-first-search/php/breadth-first-search.php: -------------------------------------------------------------------------------- 1 | count = 0; 11 | $this->data = array(); 12 | } 13 | 14 | public function enqueue($key, Person $val) 15 | { 16 | if (!in_array($key, $this->data)) { 17 | $this->count++; 18 | } 19 | $this->data[$key] = $val; 20 | } 21 | 22 | public function dequeue() 23 | { 24 | return array_shift($this->data); 25 | } 26 | } 27 | 28 | class Person 29 | { 30 | public $name = null; 31 | public $friends = array(); 32 | public $profession = null; 33 | 34 | public function __construct($name, $profession, array $friends = array()) 35 | { 36 | $this->name = $name; 37 | $this->profession = $profession; 38 | $this->friends = $friends; 39 | } 40 | } 41 | 42 | $joe = new Person('Joe', 'SEO Expert'); 43 | $chris = new Person('Chris', 'Front End Developer'); 44 | $garrett = new Person('Garrett', 'Bodybuilder'); 45 | $johanna = new Person('Johanna', 'Marketer'); 46 | $jim = new Person('Jim', 'Digital Director'); 47 | $lansana = new Person('Lansana', 'Software Engineer', array($garrett, $johanna, $jim)); 48 | $john = new Person('John', 'Client Strategy Director', array($joe, $chris)); 49 | 50 | $queue = new Queue(); 51 | $queue->enqueue('Lansana', $lansana); 52 | $queue->enqueue('John', $john); 53 | 54 | function search($queue, $profession) 55 | { 56 | $searched = array(); 57 | 58 | while ($queue->count > 0) { 59 | $person = $queue->dequeue(); 60 | 61 | if (!in_array($person->name, $searched)) { 62 | if ($person->profession === $profession) { 63 | return true; 64 | } else { 65 | for ($i = 0, $len = count($person->friends); $i < $len; $i++) { 66 | $queue->enqueue($person->friends[$i]->name, $person->friends[$i]); 67 | } 68 | } 69 | 70 | $searched[] = $person->name; 71 | } 72 | } 73 | 74 | return false; 75 | } 76 | 77 | echo search($queue, 'Digital Director'); // Returns true; match found using breadth-first search -------------------------------------------------------------------------------- /6-breadth-first-search/javascript/breadth-first-search.js: -------------------------------------------------------------------------------- 1 | class Queue { 2 | constructor() { 3 | this.count = 0; 4 | this.data = {}; 5 | } 6 | 7 | enqueue(key, val) { 8 | if (!this.data.hasOwnProperty(key)) { 9 | this.count++; 10 | } 11 | this.data[key] = val; 12 | } 13 | 14 | dequeue() { 15 | let key = Object.keys(this.data)[0], 16 | memo = this.data[key]; 17 | delete this.data[key]; 18 | this.count--; 19 | return memo; 20 | } 21 | } 22 | 23 | class Person { 24 | constructor(name, profession, friends) { 25 | this.name = name; 26 | this.profession = profession; 27 | this.friends = friends || []; 28 | } 29 | } 30 | 31 | let Ronaldinho = new Person('Ronaldinho', 'Professional Soccer Player'), 32 | Lauren = new Person('Lauren', 'Mango Seller'), 33 | Angelica = new Person('Angelica', 'Professional Volleyball Player'), 34 | Cody = new Person('Cody', 'Network Programmer'), 35 | Beyonce = new Person('Beyonce', 'Musician'), 36 | Lansana = new Person('Lansana', 'Software Engineer', [Ronaldinho, Lauren, Angelica]), 37 | Zack = new Person('Zack', 'Software Architect', [Cody]), 38 | John = new Person('John', 'Project Manager', [Ronaldinho, Angelica]), 39 | Francisco = new Person('Francisco', 'Game Developer', [Beyonce]); 40 | 41 | let graph = {}; 42 | graph['Lansana'] = Lansana; 43 | graph['Zack'] = Zack; 44 | graph['John'] = John; 45 | graph['Francisco'] = Francisco; 46 | 47 | let queue = new Queue(); 48 | queue.enqueue("Lansana", graph['Lansana']); 49 | queue.enqueue("Zack", graph['Zack']); 50 | queue.enqueue("John", graph['John']); 51 | queue.enqueue("Francisco", graph['Francisco']); 52 | 53 | function search(queue, profession) { 54 | let searched = []; 55 | 56 | while (queue.count > 0) { 57 | let person = queue.dequeue(); 58 | 59 | if (!searched[person.name]) { 60 | if (hasProfession(person, profession)) { 61 | return true; 62 | } else { 63 | for (let i = 0, len = person.friends.length; i < len; i++) { 64 | queue.enqueue(person.friends[i].name, person.friends[i]); 65 | } 66 | } 67 | 68 | searched.push(person.name); 69 | } 70 | } 71 | 72 | return false; 73 | } 74 | 75 | function hasProfession(person, profession) { 76 | return person.profession.toLowerCase() === profession.toLowerCase(); 77 | } 78 | 79 | console.log(search(queue, "Musician")); // true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Grokking Algorithms 2 | 3 | This repository contains the algorithms (in various languages) from each of the chapters in the amazing [Grokking Algorithms](https://www.manning.com/bhargava) book. 4 | 5 | I created this repository as a learning experience for myself, and in hopes that it may be useful to others. 6 | 7 | ## Chapters 8 | 9 | Below is the index of the algorithms (in various languages) used in each chapter of the book. 10 | 11 | #### Chapter 1: Introduction to Algorithms 12 | 13 | - [Go](https://github.com/LansanaCamara/grokking-algorithms/blob/master/1-introduction-to-algorithms/go/binary-search.go) 14 | - [JavaScript](https://github.com/LansanaCamara/grokking-algorithms/blob/master/1-introduction-to-algorithms/javascript/binary-search.js) 15 | - [PHP](https://github.com/LansanaCamara/grokking-algorithms/blob/master/1-introduction-to-algorithms/php/binary-search.php) 16 | 17 | #### Chapter 2: Selection Sort 18 | 19 | - [Go](https://github.com/LansanaCamara/grokking-algorithms/blob/master/2-selection-sort/go/selection-sort.go) 20 | - [JavaScript](https://github.com/LansanaCamara/grokking-algorithms/blob/master/2-selection-sort/javascript/selection-sort.js) 21 | - [PHP](https://github.com/LansanaCamara/grokking-algorithms/blob/master/2-selection-sort/php/selection-sort.php) 22 | 23 | #### Chapter 3: Recursion 24 | 25 | - [Go](https://github.com/LansanaCamara/grokking-algorithms/blob/master/3-recursion/go/recursion.go) 26 | - [JavaScript](https://github.com/LansanaCamara/grokking-algorithms/blob/master/3-recursion/javascript/recursion.js) 27 | - [PHP](https://github.com/LansanaCamara/grokking-algorithms/blob/master/3-recursion/php/recursion.php) 28 | 29 | #### Chapter 4: Quicksort 30 | 31 | - JavaScript 32 | - [Swapping in place/partitioning](https://github.com/LansanaCamara/grokking-algorithms/blob/master/4-quicksort/javascript/quicksort1.js) 33 | - [Creating new arrays](https://github.com/LansanaCamara/grokking-algorithms/blob/master/4-quicksort/javascript/quicksort2.js) 34 | - [Haskell](https://github.com/LansanaCamara/grokking-algorithms/blob/master/4-quicksort/haskell/quicksort.hs) 35 | 36 | #### Chapter 5: Hash Tables 37 | 38 | - [JavaScript](https://github.com/LansanaCamara/grokking-algorithms/blob/master/5-hash-tables/javascript/hash-tables.js) 39 | - [PHP](https://github.com/LansanaCamara/grokking-algorithms/blob/master/5-hash-tables/php/hash-tables.php) 40 | 41 | #### Chapter 6: Breadth-first Search 42 | 43 | - [JavaScript](https://github.com/LansanaCamara/grokking-algorithms/blob/master/6-breadth-first-search/javascript/breadth-first-search.js) 44 | - [PHP](https://github.com/LansanaCamara/grokking-algorithms/blob/master/6-breadth-first-search/php/breadth-first-search.php) 45 | 46 | ## More Algorithms 47 | 48 | The `/extras` directory consists of the following examples in multiple languages: 49 | 50 | 1. Combining two or more algorithms 51 | 2. Algorithms that weren't touched on in the book 52 | 53 | #### Recursive Binary Search 54 | 55 | - [Go](https://github.com/LansanaCamara/grokking-algorithms/blob/master/extras/recursive-binary-search/go/recursive-binary-search.go) 56 | - [JavaScript](https://github.com/LansanaCamara/grokking-algorithms/blob/master/extras/recursive-binary-search/javascript/recursive-binary-search.js) 57 | - [PHP](https://github.com/LansanaCamara/grokking-algorithms/blob/master/extras/recursive-binary-search/php/recursive-binary-search.php) 58 | 59 | ## Contributing 60 | 61 | Feel free to make pull requests for code improvements, new languages, etc. --------------------------------------------------------------------------------