Finding the longest increasing subsequence (LIS) in a sequence of numbers is a classic problem in computer science and dynamic programming. The goal is to identify the longest subsequence where each element is greater than the preceding one. This problem can be approached in several ways, with varying time complexities. Below, I will outline the most common methods, provide practical examples, and highlight best practices and common mistakes.
The dynamic programming approach is one of the most efficient ways to solve the LIS problem. The idea is to build a table that stores the length of the longest increasing subsequence that ends with each element of the array.
function longestIncreasingSubsequence(arr) {
if (arr.length === 0) return 0;
const dp = new Array(arr.length).fill(1);
for (let i = 1; i < arr.length; i++) {
for (let j = 0; j < i; j++) {
if (arr[i] > arr[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
return Math.max(...dp);
}
const exampleArray = [10, 22, 9, 33, 21, 50, 41, 60, 80];
console.log(longestIncreasingSubsequence(exampleArray)); // Output: 6
For a more efficient solution, especially for larger datasets, a combination of dynamic programming and binary search can be used. This approach reduces the time complexity to O(n log n).
function longestIncreasingSubsequence(arr) {
const sub = [];
for (let num of arr) {
let left = 0, right = sub.length;
while (left < right) {
const mid = Math.floor((left + right) / 2);
if (sub[mid] < num) {
left = mid + 1;
} else {
right = mid;
}
}
if (left === sub.length) {
sub.push(num);
} else {
sub[left] = num;
}
}
return sub.length;
}
const exampleArray = [10, 22, 9, 33, 21, 50, 41, 60, 80];
console.log(longestIncreasingSubsequence(exampleArray)); // Output: 6