Compare commits

...

3 Commits

Author SHA1 Message Date
Aryaan Kharbade
ec869a6e90
Merge fdbb4951ee into ca3d16dcce 2024-09-03 18:38:15 +00:00
Aryaan Kharbade
fdbb4951ee
Merge branch 'trekhleb:master' into master 2024-09-04 00:08:12 +05:30
Aryaan Kharbade
f09c41a467 optimised TC of longest increasing subsequence 2024-06-29 16:45:57 +05:30

View File

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