Added Efficient LIS (nlog(n))

This commit is contained in:
Bruce Feldman 2018-08-10 17:12:40 -04:00
parent 70ec623cbf
commit 5cf8ac2555
2 changed files with 64 additions and 0 deletions

View File

@ -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);
});
});

View File

@ -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;
}