例如:给定一个长度为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; } }