optimised TC of longest increasing subsequence

This commit is contained in:
Aryaan Kharbade 2024-06-29 16:45:57 +05:30
parent 2c67b48c21
commit f09c41a467

View File

@ -1,53 +1,41 @@
/** /**
* Dynamic programming approach to find longest increasing subsequence. * Optimized approach to find longest increasing subsequence.
* Complexity: O(n * n) * Complexity: O(n * log n)
* *
* @param {number[]} sequence * @param {number[]} sequence
* @return {number} * @return {number}
*/ */
export default function dpLongestIncreasingSubsequence(sequence) { export default function dpLongestIncreasingSubsequence(sequence) {
// Create array with longest increasing substrings length and if (sequence.length === 0) {
// fill it with 1-s that would mean that each element of the sequence return 0;
// is itself a minimum increasing subsequence. }
const lengthsArray = Array(sequence.length).fill(1);
let previousElementIndex = 0; // This will store the smallest tail value for all increasing subsequences
let currentElementIndex = 1; // with length i+1 in tail[i].
const tails = [];
while (currentElementIndex < sequence.length) { sequence.forEach((num) => {
if (sequence[previousElementIndex] < sequence[currentElementIndex]) { let left = 0;
// If current element is bigger then the previous one then let right = tails.length;
// current element is a part of increasing subsequence which
// length is by one bigger then the length of increasing subsequence // Binary search for the insertion point of the current element.
// for previous element. while (left < right) {
const newLength = lengthsArray[previousElementIndex] + 1; const mid = Math.floor((left + right) / 2);
if (newLength > lengthsArray[currentElementIndex]) { if (tails[mid] < num) {
// Increase only if previous element would give us bigger subsequence length left = mid + 1;
// then we already have for current element. } else {
lengthsArray[currentElementIndex] = newLength; right = mid;
} }
} }
// Move previous element index right. // If left is equal to the length of tails, it means we are adding a new subsequence.
previousElementIndex += 1; if (left === tails.length) {
tails.push(num);
// If previous element index equals to current element index then } else {
// shift current element right and reset previous element index to zero. // Otherwise, we are updating an existing subsequence with a new tail value.
if (previousElementIndex === currentElementIndex) { tails[left] = num;
currentElementIndex += 1;
previousElementIndex = 0;
}
} }
});
// Find the biggest element in lengthsArray. return tails.length;
// This number is the biggest length of increasing subsequence.
let longestIncreasingLength = 0;
for (let i = 0; i < lengthsArray.length; i += 1) {
if (lengthsArray[i] > longestIncreasingLength) {
longestIncreasingLength = lengthsArray[i];
}
}
return longestIncreasingLength;
} }