1.例题
题目描述
给你一个长度为n的数组,求最长的严格上升子序列的长度。
输入描述:
第一行一个整数n,表示数组长度
第二行n个整数,表示数组中的元素。1 <= n <= 100000
输出描述:
输出一行,表示答案。
示例1
输入
5
1 2 2 2 3
输出
3
说明
最长的上升子序列为[1,2,3],长度为3.
2.题解
2.1 动态规划题解
#include <bits/stdc++.h>
using namespace std;
#define int long long
int longestIncreasingSubsequence(const vector<int>& nums) {
int n = nums.size();
vector<int> dp(n, 1); // 初始化 dp 数组
int maxLength = 1; // 至少为 1,因为每个元素自身是一个长度为 1 的子序列
// 动态规划求解 LIS
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);
}
}
maxLength = max(maxLength, dp[i]);
}
return maxLength;
}
signed main() {
int n;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; ++i) {
cin >> nums[i];
}
cout <<longestIncreasingSubsequence(nums) << endl;
return 0;
}
2.2二分优化
#include <bits/stdc++.h>
using namespace std;
int binarySearch(const vector<int>& tails, int val) {
int left = 0, right = tails.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (tails[mid] >= val) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
int longestIncreasingSubsequence(const vector<int>& nums) {
vector<int> tails;
for (int num : nums) {
int pos = binarySearch(tails, num);
if (pos == tails.size()) {
tails.push_back(num);
//使用二分查找算法在 tails 数组中查找一个位置 pos,使得 tails[pos-1] < num <= tails[pos]。
//如果找不到这样的位置(即 num 大于 tails 中所有元素),pos 将等于 tails.size()。
} else {
tails[pos] = num; // 更新 tails[pos] 为更小的值
}
}
return tails.size();
}
int main() {
int n;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; ++i) {
cin >> nums[i];
}
cout << longestIncreasingSubsequence(nums) << endl;
return 0;
}
3.总结
二分nlogn
动态规划n*n