From 5cf8ac25552c295b7b1769e3c8fa342b975d9e1e Mon Sep 17 00:00:00 2001 From: Bruce Feldman Date: Fri, 10 Aug 2018 17:12:40 -0400 Subject: [PATCH] Added Efficient LIS (nlog(n)) --- .../longestIncreasingSubsequence.test.js | 36 +++++++++++++++++++ .../longestIncreasingSubsequence.js | 28 +++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/algorithms/sets/longest-increasing-subsequence/__test__/longestIncreasingSubsequence.test.js create mode 100644 src/algorithms/sets/longest-increasing-subsequence/longestIncreasingSubsequence.js diff --git a/src/algorithms/sets/longest-increasing-subsequence/__test__/longestIncreasingSubsequence.test.js b/src/algorithms/sets/longest-increasing-subsequence/__test__/longestIncreasingSubsequence.test.js new file mode 100644 index 00000000..4a444a89 --- /dev/null +++ b/src/algorithms/sets/longest-increasing-subsequence/__test__/longestIncreasingSubsequence.test.js @@ -0,0 +1,36 @@ +import longestIncreasingSubsequence from '../longestIncreasingSubsequence'; + +describe('LongestIncreasingSubsequence', () => { + it('should find longest increasing subsequence length', () => { + // Should be: + // 9 or + // 8 or + // 7 or + // 6 or + // ... + expect(longestIncreasingSubsequence([ + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + ])).toBe(1); + + // Should be: + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + expect(longestIncreasingSubsequence([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + ])).toBe(10); + + // Should be: + // -1, 0, 2, 3 + expect(longestIncreasingSubsequence([ + 3, 4, -1, 0, 6, 2, 3, + ])).toBe(4); + + // Should be: + // 0, 2, 6, 9, 11, 15 or + // 0, 4, 6, 9, 11, 15 or + // 0, 2, 6, 9, 13, 15 or + // 0, 4, 6, 9, 13, 15 + expect(longestIncreasingSubsequence([ + 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15, + ])).toBe(6); + }); +}); diff --git a/src/algorithms/sets/longest-increasing-subsequence/longestIncreasingSubsequence.js b/src/algorithms/sets/longest-increasing-subsequence/longestIncreasingSubsequence.js new file mode 100644 index 00000000..88e97acc --- /dev/null +++ b/src/algorithms/sets/longest-increasing-subsequence/longestIncreasingSubsequence.js @@ -0,0 +1,28 @@ +/** + * Efficient approach to find longest increasing subsequence. + * Complexity: O(n * log(n)) + * + * @param {number[]} sequence + * @return {number} + */ +export default function LongestIncreasingSubsequence(sequence) { + // Retrieves the smallest number greater or equal to val in sorted arr. + function upperBound(arr, val) { + let lo = 0; + let hi = arr.length; + + while (lo < hi) { + const mid = lo + Math.floor((hi - lo) / 2); + if (arr[mid] < val) { + lo = mid + 1; + } else { + hi = mid; + } + } + return hi; + } + + const lis = []; + sequence.forEach((val) => { lis[upperBound(lis, val)] = val; }); + return lis.length; +}