例如:给定一个长度为8的数组A{1,3,5,2,4,6,7,8},则其最长的单调递增子序列为{1,2,4,6,7,8},长度为6.
第一行包含一个整数T,代表测试数据组数。
对于每组测试数据: N-数组的长度
a1 a2 ... an (需要计算的数组)
保证:
1<=N<=3000,0<=ai<=MAX_INT.
对于每组数据,输出一个整数,代表最长递增子序列的长度。
2 7 89 256 78 1 46 78 8 5 6 4 8 2 17
3 3
#include<iostream>
#include"vector"
using namespace std;
int main()
{
vector<int>result;
vector<int>result1;
vector<int>num;
int T;
cin >> T;
while (T--)
{
int a;
cin >> a;
int n = a;
while (a--)
{
int b;
cin >> b;
num.push_back(b);
result.push_back(1);
}
for (int i = 0; i < n; i++)
{
result[i] = 1;
for (int j = i - 1; j >= 0; j--)
{
if (num[i]>num[j] && result[i] < (result[j] + 1))
result[i] = result[j] + 1;
}
}
int max = -1;
for (int i = 0; i < n; i++)
{
if (result[i]>max)
{
max = result[i];
}
}
result.clear();
num.clear();
result1.push_back(max);
}
for (int i = 0; i < result1.size(); i++)
{
cout << result1[i] << endl;
}
}
第一种方法最普通的方法dp
#include <stdio.h>
int d[3005];
int dp(int a[], int n)
{
int i, j;
int tmp;
int max=1;
for(i=0;i<n;i++)
{
d[i]=1;
for(j=i-1;j>=0;j--)
{
if(a[j]<a[i])
{
tmp=d[j]+1;
if(tmp>d[i])
d[i]=tmp;
}
}
if(d[i]>max)
max=d[i];
}
return max;
}
int main()
{
int i;
int n,k;
int a[3005];
scanf("%d", &n);
while(n--)
{
scanf("%d", &k);
for(i=0;i<k;i++)
scanf("%d", a+i);
printf("%d\n",dp(a,k));
}
return 0;
}
//第二种方法qsort+LCS,但是通过不了,因为内存超过限制
#include <stdio.h>
#include <string.h>
void swap(int*arr, int i, int j)
{
int tmp = arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
void qsort(int s[], int l, int r)
{
if(l<r)
{
int i=l;
for(int j=i+1;j<=r;j++)
if(s[j]<s[l])
swap(s,++i,j);
swap(s,i,l);
qsort(s,l,i-1);
qsort(s,i+1,r);
}
}
int dp[3005][3005];
int a[3005],b[3005];
int LCS(int s[], int sc[], int len)
{
for(int i=1; i<=len;i++)
for(int j=1;j<=len;j++)
{
if(s[i-1] == sc[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else if(dp[i-1][j]>dp[i][j-1])
dp[i][j]=dp[i-1][j];
else
dp[i][j]=dp[i][j-1];
}
return dp[len][len];
}
int main()
{
int i;
int n,k;
scanf("%d", &n);
while(n--)
{
scanf("%d", &k);
for(i=0;i<k;i++)
scanf("%d", a+i);
memcpy(b,a,sizeof(int)*k);
qsort(b,0,k-1);
printf("%d\n",LCS(a,b,k));
}
return 0;
}
动态规划题,一般先写出问题的最优子结构的关系式,如下:
d[n] = max{ d[i]+1 | a[i] < a[n], 0 =< i <= n }
其中,a[i]表示数组下标为i的数,d[i]表示以a[i]为结尾的递增序列的长度。
很明显,数组的最长递增子序列的长度为d[0]到d[n]中的一个值
代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int T = scanner.nextInt();
for (int i = 0; i < T; i++) {
int n = scanner.nextInt();
int[] array = new int[n];
for (int j = 0; j < n; j++) {
array[j] = scanner.nextInt();
}
int len = getLisLen(array, n);
System.out.println(len);
}
scanner.close();
}
public static int getLisLen(int[] array, int n) {
int[] d = new int[n];
int max = 0;
for (int i = 0; i < n; i++) {
d[i] = 1;
for (int j = 0; j < i; j++) {
if (array[j] < array[i]) {
d[i] = Integer.max(d[i], d[j]+1);
}
}
max = Integer.max(max, d[i]);
}
return max;
}
} #include <iostream>
#include <vector>
using namespace std;
int main(){
int T;
cin >> T;
while(T--){
int n;
cin >> n;
vector<int> nums(n, 0);
for(int i=0;i<n;i++){
cin >> nums[i];
}
vector<int> keep;
for(int i=0;i<n;i++){
auto it = lower_bound(keep.begin(), keep.end(), nums[i]);
if(it!=keep.end()){
*it = nums[i];
}
else{
keep.push_back(nums[i]);
}
}
cout << keep.size() << endl;
}
return 0;
}
import java.util.Scanner;
public class Main {
private static int[] getdp1(int[] arr) {
int[] dp = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (arr[i] > arr[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
return dp;
}
private static int generateLIS(int[] arr, int[] dp) {
int len = 0;
int index = 0;
for (int i = 0; i < dp.length; i++) {
if (dp[i] > len) {
len = dp[i];
index = i;
}
}
return len;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){
int T = in.nextInt();
for (int i = 0; i < T; i++){
int n = in.nextInt();
int[] a = new int[n];
for(int j = 0; j < n; j++){
a[j] = in.nextInt();
}
int[] dp = getdp1(a);
System.out.println(generateLIS(a, dp));
}
}
}
}
}
#include<iostream> using namespace std;
int getMaxLength(int A[], int N)
{
int max = 1;
int *length = new int[N];
for(int i = 0; i < N; i++)
{
length[i] = 1;
for(int j = i-1; j >= 0; j--) //获得第i个元素能够得到的最大长度
{
if(A[i] > A[j])
{
int temp = length[j] + 1;
if(length[i] < temp)
length[i] = temp;
}
}
if(length[i] > max) //get max length
max = length[i];
}
delete []length;
return max;
}
int main()
{
int T;
int N;
cin>>T;
while(T--)
{
cin>>N;
int *A = new int[N];
for(int i = 0; i < N; i++)
{
cin>>A[i];
}
cout<<getMaxLength(A, N)<<endl;
delete []A;
}
return 0;
}
#include "iostream"
using namespace std;
int main(){
int T,N,i,j;
int a[3005] = {0};
int dp[3005] = {0};
cin>>T;
while(T--){
int count = 0;
cin>>N;
for(i = 0;i < N; i++)
cin>>a[i];
for(i = 0;i < 3005; i++)
dp[i] = 1;
for(i = 0;i < N; i++)
for(j = i + 1;j < N; j++){
if(a[i] < a[j]){
dp[j] = max(dp[j],dp[i]+1);
}
}
int Max = 0;
for(i = 0;i < N; i++){
if(dp[i] > Max)
Max = dp[i];
}
cout<<Max<<endl;
}
return 0;
} package coding_test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class LongestIncreasingSubSequence {
public static int logSeq(int[] seq) {
int[] f = new int[seq.length];
f[0] = 1;
for(int i = 1; i < seq.length; i++) {
f[i] = 1;
for(int j = 0; j < i; j++) {
if(seq[i] > seq[j] && f[i] <= f[j]) {
f[i] = f[j] + 1;
}
}
}
int maxLength = -1;
for(int i = 0; i < f.length; i++) {
if(maxLength < f[i]) {
maxLength = f[i];
}
}
return maxLength;
}
public static void main(String[] args) {
try {
BufferedReader strin=new BufferedReader(new InputStreamReader(System.in));
System.out.print("请输入组数:");
String group_numb = strin.readLine();
int numb = Integer.parseInt(group_numb); //number of groups
int[][] arr = new int[numb][]; // all group arrays
int [] length = new int[numb]; //each group length
int k =1, j=0;
while(numb > 0) {
System.out.print("请输入第"+k+"组长度:");
length[j] = Integer.parseInt(strin.readLine());
System.out.print("请输入第"+k+"组数据:");
String[] string = strin.readLine().split(" ");
arr[j] = new int[length[j]];
for(int i=0; i<string.length;i++) {
arr[k-1][i] = Integer.parseInt(string[i]);
}
// for(int[] a:arr) {
// System.out.println(Arrays.toString(a));
// }
k++;
numb--;
j++;
}
int m = 0;
//j is equal to the original numb
while(j > 0) {
System.out.print("第"+ (m+1) +"组最长递增子序列的长度:" + logSeq(arr[m])+"\n");
// System.out.println(logSeq(arr[m]));
m++;
j--;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
#include <iostream>usingnamespacestd;intmain(){intT;while(cin>>T){for(inti=0; i<T; i++){intN;cin>>N;intarr[N],dp[N];for(intj=0; j<N; j++){cin>>arr[j];dp[j]=1;}intmax=1;for(intk=1; k<N; k++){for(inth=0; h<k; h++){if(arr[h]<arr[k]){if(dp[h]+1>dp[k])dp[k]=dp[h]+1;}}if(dp[k]>max)max=dp[k];}cout << max << endl;}}return0;}
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
int findLongest(vector<int> A, int n) {
// write code here
if (!n)
return 0;
vector<int> dp(n, 1);
multiset<int> help;
help.insert(A[0]);
for (int i = 1; i < n; i++) {
multiset<int>::iterator itor = help.lower_bound(A[i]);
if (itor != help.end()) {
help.erase(itor);
help.insert(A[i]);
int num = 1;
multiset<int>::iterator iter = help.begin();
for (; iter != help.end(); iter++) {
if (*iter == A[i])
break;
num++;
}
dp[i] = num;
}
else {
help.insert(A[i]);
dp[i] = help.size();
}
}
int length = dp[0];
for (int i = 1; i < n; i++) {
if (length < dp[i]) {
length = dp[i];
}
}
return length;
}
int main() {
using namespace std;
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> height(n);
for (int i = 0; i < n; i++) {
cin >> height[i];
}
cout << findLongest(height, n) << endl;
}
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
using std::vector;
int main(void){
int times;
int T;
cin >> times;
for(int q = 0; q < times; q++){
cin >> T;
vector<int> a;
vector<int> nn(T, 1);
int temp = 0;
int lm = 1;
for(int i = 0; i < T; i++){
cin >> temp;
a.push_back(temp);
}
for(int i = 0; i < T - 1; i++){
for(int k = i; k >= 0; k--){
if((a[i + 1] > a[k]) && (nn[i + 1] < nn[k] + 1))
nn[i + 1] = nn[k] + 1;
}
}
for(int i = 0; i < T; i++)
if(lm < nn[i]) lm = nn[i];
cout << lm << endl;
}
return 0;
}
import java.util.*;
public class Main{
public static int getLIS(int[] arr) {
int[] dp = new int[arr.length];
int[] ends = new int[arr.length];
ends[0] = arr[0];
dp[0] = 1;
int right = 0;
int l = 0 , r = 0 , m = 0;
for (int i = 1; i < arr.length; i++) {
l = 0;
r = right;
while (l <= r) {
m = (l + r) / 2;
if (arr[i] > ends[m]) {
l = m + 1;
} else {
r = m - 1;
}
}
right = Math.max(right, l);
ends[l] = arr[i];
dp[i] = l + 1;
}
//以上是获取dp数组,引入辅助数组+二分查找,复杂度O(NlogN)
int len = 0;
for (int i = 0; i < dp.length; i++)
if (dp[i] > len)
len = dp[i];
return len;
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int t = in.nextInt();
while(t--!=0){
int n = in.nextInt();
int[] arr = new int[n];
for(int i=0 ; i<n ; i++){
arr[i] = in.nextInt();
}
System.out.println(getLIS(arr));
}
}
}
}
import java.util.Scanner;
public class Main {
public static void main(String[] args){
int len;
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int size = in.nextInt();
for(int i=0;i<size;i++) {
int len = in.nextInt();
int[] data = new int[len];
for(int j=0;j<len;j++){
data[j] = in.nextInt();
}
len = getDp(data);
System.out.println(len);
}
}
}
public static int getDp(int[] arr) {
int[] dp = new int[arr.length];
int[] end = new int[arr.length];
end[0] = arr[0];
dp[0] = 1;
int l,r,m,right=0;
for(int i=1;i<arr.length;i++) {
l = 0;
r = right;
while (l<=r) {
m = (l+r)/2;
if(arr[i]>end[m]) {
l = m+1;
}
else {
r = m-1;
}
}
right = Math.max(right,l);
end[l]= arr[i];
dp[i] = l+1;
}
int len = 0;
for(int i=0;i<dp.length;i++) {
if(dp[i]>len) {
len = dp[i];
}
}
return len;
}
}