diff --git a/QuickSelect.js b/QuickSelect.js new file mode 100644 index 0000000000..473a577a94 --- /dev/null +++ b/QuickSelect.js @@ -0,0 +1,68 @@ +/** + * QuickSelect is an algorithm to find the kth smallest number + * + * Notes: + * -QuickSelect is related to QuickSort, thus has optimal best and average + * case (O(n)) but unlikely poor worst case (O(n^2)) + * -This implementation uses randomly selected pivots for better performance + * + * @complexity: O(n) (on average ) + * @complexity: O(n^2) (worst case) + * @flow + */ + +function QuickSelect (items, kth) { + return RandomizedSelect(items, 0, items.length - 1, kth) +} + +function RandomizedSelect ( + items, + left, + right, + i +) { + if (left === right) return items[left] + + const pivotIndex = RandomizedPartition(items, left, right) + const k = pivotIndex - left + 1 + + if (i === k) return items[pivotIndex] + if (i < k) return RandomizedSelect(items, left, pivotIndex - 1, i) + + return RandomizedSelect(items, pivotIndex + 1, right, i - k) +} + +function RandomizedPartition (items, left, right) { + const rand = getRandomInt(left, right) + Swap(items, rand, right) + return Partition(items, left, right) +} + +function Partition (items, left, right) { + const x = items[right] + let pivotIndex = left - 1 + + for (let j = left; j < right; j++) { + if (items[j] <= x) { + pivotIndex++ + Swap(items, pivotIndex, j) + } + } + + Swap(items, pivotIndex + 1, right) + + return pivotIndex + 1 +} + +function getRandomInt (min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min +} + +function Swap (arr, x, y) { + const temp = arr[x] + arr[x] = arr[y] + arr[y] = temp +} + +// testing +console.log(QuickSelect([1, 4, 2, -2, 4, 5])) diff --git a/Sorts/Heapsort.js b/Sorts/Heapsort.js new file mode 100644 index 0000000000..d250d41ea9 --- /dev/null +++ b/Sorts/Heapsort.js @@ -0,0 +1,48 @@ +let arrayLength = 0 + +/* to create MAX array */ + +function heapRoot (input, i) { + const left = 2 * i + 1 + const right = 2 * i + 2 + let max = i + + if (left < arrayLength && input[left] > input[max]) { + max = left + } + + if (right < arrayLength && input[right] > input[max]) { + max = right + } + + if (max !== i) { + swap(input, i, max) + heapRoot(input, max) + } +} + +function swap (input, indexA, indexB) { + const temp = input[indexA] + + input[indexA] = input[indexB] + input[indexB] = temp +} + +function heapSort (input) { + arrayLength = input.length + + for (let i = Math.floor(arrayLength / 2); i >= 0; i -= 1) { + heapRoot(input, i) + } + + for (let i = input.length - 1; i > 0; i--) { + swap(input, 0, i) + arrayLength-- + + heapRoot(input, 0) + } +} + +const arr = [3, 0, 2, 5, -1, 4, 1] +heapSort(arr) +console.log(arr) diff --git a/maths/ReverseString.js b/maths/ReverseString.js new file mode 100644 index 0000000000..8709e17df9 --- /dev/null +++ b/maths/ReverseString.js @@ -0,0 +1,45 @@ +/** + * A short example showing how to reverse a string + * @flow + */ + +/** + * Create a new string and append + * @complexity O(n) + */ + +function ReverseStringIterative (string) { + let reversedString = '' + let index + + for (index = string.length - 1; index >= 0; index--) { + reversedString += string[index] + } + + return reversedString +} + +/** + * JS disallows string mutation so we're actually a bit slower. + * + * @complexity: O(n) + * + * 'some' -> 'eoms' -> 'emos' + */ + +function ReverseStringIterativeInplace (string) { + const _string = string.split('') + + for (let i = 0; i < Math.floor(_string.length / 2); i++) { + const first = _string[i] + const second = _string[_string.length - 1 - i] + _string[i] = second + _string[_string.length - 1 - i] = first + } + + return _string.join('') +} + +// testing +console.log(ReverseStringIterative('Javascript')) +console.log(ReverseStringIterativeInplace('Javascript'))