最长上升子序列C++
时间: 2025-05-03 20:37:10 浏览: 26
### C++ 实现最长上升子序列 (LIS) 算法
以下是基于动态规划方法实现的最长上升子序列 (LIS) 的完整代码示例:
```cpp
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n; // 输入序列长度
int a[n + 1], dp[n + 1];
for (int i = 1; i <= n; ++i) {
cin >> a[i]; // 输入序列元素
}
for (int i = 1; i <= n; ++i) {
dp[i] = 1; // 初始化 DP 数组
for (int j = 1; j < i; ++j) {
if (a[j] < a[i]) { // 如果前面有更小的数,则更新状态
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
int lis_length = 0;
for (int i = 1; i <= n; ++i) {
lis_length = max(lis_length, dp[i]); // 找到最大的 LIS 长度
}
cout << lis_length; // 输出结果
return 0;
}
```
#### 解释
上述代码实现了通过动态规划计算最长上升子序列的功能。核心思想是维护一个 `dp` 数组,其中 `dp[i]` 表示以第 `i` 个元素结尾的最长上升子序列的长度[^2]。
对于每一个位置 `i`,程序会检查之前所有的位置 `j` (`j < i`) 是否满足条件 `a[j] < a[i]`。如果满足,则尝试更新当前的最大值 `dp[i] = max(dp[i], dp[j] + 1)`[^3]。
最终的结果存储在变量 `lis_length` 中,它是 `dp` 数组中的最大值。
---
### 时间复杂度分析
该算法的时间复杂度为 \(O(n^2)\),因为存在两层嵌套循环。外层循环遍历每个元素,而内层循环则比较当前元素与之前的元素关系。这种时间复杂度适用于较小规模的数据集(如 \(n \leq 1000\)),但对于更大的数据量可能需要优化至 \(O(n \log n)\)[^5]。
---
### 更高效的解决方案 (\(O(n \log n)\))
为了进一步提高效率,可以通过二分查找配合贪心策略来降低时间复杂度。下面是改进后的代码版本:
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n; // 输入序列长度
vector<int> a(n), tails;
for (int i = 0; i < n; ++i) {
cin >> a[i]; // 输入序列元素
}
for (auto num : a) {
auto it = lower_bound(tails.begin(), tails.end(), num); // 使用二分查找定位插入位置
if (it == tails.end()) {
tails.push_back(num); // 若找不到合适的位置,则扩展尾巴
} else {
*it = num; // 否则替换掉第一个大于等于它的数
}
}
cout << tails.size(); // 尾巴数组大小即为 LIS 长度
return 0;
}
```
此版本利用了一个辅助数组 `tails` 来记录潜在的候选序列,并借助标准库函数 `lower_bound()` 进行快速查找操作[^4]。
---
阅读全文
相关推荐


















