题目:
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
思路:
1、动态规划:设dp[i]表示已nums[i]结尾的最长子序列,则状态转移方程为:dp[i] = max(dp[j] + 1), j < i && nums[j] < nums[i]。因此,采用两种循环就可以搞定,时间复杂度是O(n^2),空间复杂度是O(n)。
2、二分查找:这是求解最长递增子序列的一个经典算法。我们在遍历数组元素过程中维护一个单调递增的子数组。每次遍历到一个新元素,就查找比它大的第一个元素,然后替换这一元素;如果单调递增子数组中的所有元素都比该元素小,则将该元素添加到递增子序列中,并更新长度。该算法的空间复杂度是O(n),时间复杂度是O(nlogn)。
代码:
1、动态规划:
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if(nums.size() == 0) {
return 0;
}
vector<int> dp(nums.size(), 1);
for(int i = 1; i < nums.size(); ++i) {
for(int j = 0; j < i; ++j) {
if((nums[j] < nums[i]) && (dp[i] < dp[j] + 1)) {
dp[i] = dp[j] + 1;
}
}
}
return *max_element(dp.begin(), dp.end());
}
};
2、二分查找:
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//vector<int> parent(nums.size()); // In case we need reconstruct the LIS
vector<int> increasing_subarray(nums.size() + 1);
int length = 0;
for(int i = 0; i < nums.size(); ++i) {
int low = 1, high = length; // Binary search
while(low <= high) {
int mid = std::ceil((low + high) / 2);
if(nums[increasing_subarray[mid]] < nums[i]) {
low = mid + 1;
}
else {
high = mid - 1;
}
}
int pos = low;
//parent[i] = increasing_subarray[pos - 1]; // Update parent/previous element for LIS
increasing_subarray[pos] = i; // Replacing or append
if(pos > length) {
length = pos;
}
}
/*vector<int> LIS(nums.size()); // Generate LIS by traversing parent array
int k = increasing_subarray[length];
for(int j = length - 1; j >= 0; --j)
{
LIS[j] = nums[k];
k = parent[k];
}*/
return length;
}
};
本文介绍了一种求解最长递增子序列(LIS)的经典算法。提供了两种解决方案:一是基于动态规划的方法,时间复杂度为O(n²);二是采用二分查找优化,将时间复杂度降低至O(n log n)。适用于处理整数序列,寻找最长递增子序列的长度。
1380

被折叠的 条评论
为什么被折叠?



