Longest Increasing Subsequence medium
Problem Statement
Given an integer array nums
, return the length of the longest strictly increasing subsequence.
A subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements. For example, [3,6,2,7]
is a subsequence of the array [0,3,1,6,2,2,7]
.
Example 1
Input: nums = [10,9,2,5,3,7,101,18] Output: 4 Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Example 2
Input: nums = [0,1,0,3,2,3] Output: 4
Steps and Explanation
This problem can be solved efficiently using dynamic programming. We'll create a DP array dp
where dp[i]
stores the length of the longest increasing subsequence ending at index i
.
-
Initialization: Initialize
dp[i] = 1
for alli
. This is because the minimum length of an increasing subsequence ending at any index is 1 (the element itself). -
Iteration: Iterate through the
nums
array. For each elementnums[i]
, iterate through the elements before it (from 0 toi-1
). -
Comparison: If
nums[j] < nums[i]
(meaning we found a smaller element that can be part of an increasing subsequence ending ati
), then we can potentially extend the subsequence. We updatedp[i]
as follows:dp[i] = max(dp[i], dp[j] + 1)
. This means the length of the LIS ending ati
is the maximum of its current length and the length of the LIS ending atj
plus 1 (because we're addingnums[i]
to that subsequence). -
Finding the Maximum: After iterating through the entire array, the maximum value in the
dp
array will be the length of the longest increasing subsequence.
Code (C++)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int lengthOfLIS(vector<int>& nums) {
if (nums.empty()) {
return 0;
}
int n = nums.size();
vector<int> dp(n, 1); // Initialize dp array with 1s
for (int i = 1; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
int maxLength = *max_element(dp.begin(), dp.end());
return maxLength;
}
int main() {
vector<int> nums1 = {10, 9, 2, 5, 3, 7, 101, 18};
cout << "Length of LIS for nums1: " << lengthOfLIS(nums1) << endl; // Output: 4
vector<int> nums2 = {0, 1, 0, 3, 2, 3};
cout << "Length of LIS for nums2: " << lengthOfLIS(nums2) << endl; // Output: 4
vector<int> nums3 = {};
cout << "Length of LIS for nums3: " << lengthOfLIS(nums3) << endl; // Output: 0
return 0;
}
Time and Space Complexity
- Time Complexity: O(n^2), due to the nested loops in the dynamic programming approach.
- Space Complexity: O(n), to store the
dp
array. We could potentially reduce this to O(1) using a more advanced approach (like binary search) but that would involve slightly increased complexity in other areas. This solution prioritizes readability and clarity.