问题描述:
给定一个序列,要求找到其中最长的一个升序子序列。也就是说,要找到一个子序列,使得其中的元素按照从小到大的顺序排列,并且长度最长。
例如:(2,7,1,5,6,4,3,8,9)中求最长上升子序列 最长的为4,为什么呢?
解决方法:
一种常用的动态规划方法来解决最长上升子序列问题是使用一个辅助数组dp。dp[i]表示以第i个元素结尾的最长上升子序列的长度。
具体步骤:
- 创建一个长度与给定数组相同的dp数组,用于存储以当前元素结尾的最长上升子序列的长度。
- 初始化dp数组的所有元素为1,因为每个元素本身就是一个长度为1的上升子序列。
- 遍历数组,对于每个元素nums[i],遍历其之前的所有元素nums[j],如果nums[i]大于nums[j],则更新dp[i]为dp[j]+1。
- 最后返回dp数组中的最大值即为最长上升子序列的长度。
伪代码:
function lengthOfLIS(nums) {
const n = nums.length;
const dp = new Array(n).fill(1);
for (let i = 0; i < n; i++) {
for (let j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
return Math.max(...dp);
}
代码实现(复杂版):
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int a[100];
int dp[100];
int main() {
int i, n;
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d", &a[i]);
}
int max_length=0;
for(int i=1;i<=n;i++){
dp[i]=1;
for(int j=1;j<i;j++){
if(a[j]<a[i]){
dp[i]=max(dp[i],dp[j]+1);
}
}
printf("dp[%d]=%d\n",i,dp[i]);
max_length = max(max_length, dp[i]);
}
cout << "最大子序列长度: " << max_length << endl;
return 0;
}
总结:
这段代码使用动态规划的方法解决了最长上升子序列的问题,通过遍历数组并更新dp数组来求解最长上升子序列的长度。代码实现了功能,但是有一些可以改进的地方:
- 变量i在外部已经定义,不需要在for循环中再次定义。
- 数组a和dp的大小固定为100,可能不够灵活,可以考虑动态分配内存。
- 使用了C语言的输入输出函数scanf和printf,可以考虑使用C++的cin和cout进行输入输出。
代码实现(改进版):
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> a(n);
vector<int> dp(n, 1);
for(int i = 0; i < n; i++) {
cin >> a[i];
}
int max_length = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < i; j++){
if(a[j] < a[i]){
dp[i] = max(dp[i], dp[j] + 1);
}
}
max_length = max(max_length, dp[i]);
}
cout << "最大子序列长度: " << max_length << endl;
return 0;
}
总结:改进版的 统一C++输入输出流,更符合C++风格,主要是本人C和C++相互使用,导致有时随意使用了,本人小菜鸡一个,欢迎各路大神点评指正~