一、最长递增子序列
例如:{5,3,4,8,6,7 } 最长递增子序列的长度为4,序列为{3、4、6、7}
用a[i]记录原始数据数组。
用d[i]来记录到a[i]这个数据为止时的最大递增子序列的长度,初始化为1.
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s = new Scanner(System.in);
int n = s.nextInt(); // 序列中数的个数
int[] a = new int[n];
int[] d = new int[n];
for (int i = 0; i < n; i++) {
a[i] = s.nextInt();
d[i] = 1; //用来记录到第i个数据为止时的最长递增子序列长度
}
for(int i=1;i<n;i++) {
for (int j=0;j<i;j++) {
//遍历a[i]前面的数据a[j],所有小于a[i]的数d[j]+1,再取这些d[j]中的最大值。
if(a[j]<a[i]) {
d[i]=Math.max(d[i],d[j]+1);
}
}
}
System.out.println(d[n-1]);
}
}
二、最长公共子序列
例如:数组 A{5,6, 7, 1, 2, 8},
排序得到数组 A‘{1, 2, 5, 6, 7, 8},
然后找出数组A和A’的最长公共子序列即可。
显然这里最长公共子序列为{5, 6, 7, 8},也就是原数组A最长递增子序列。
以下解释图片来自其他博客:
如图所示:公共子序列为BCBA,令i=0;j=0的行列全为0,其他网格相同则加1,不同则找左边或者上边的最大值填入。即可统计出最大的公共子序列长度。
[外链图片转存失败(img-FR6lDEz1-1567672217104)(https://img-my.csdn.net/uploads/201207/29/1343545894_4901.PNG)]
状态方程如下:
[外链图片转存失败(img-A9Da79R8-1567672217106)(https://img-my.csdn.net/uploads/201207/29/1343545870_7376.PNG)]
来个题练练:
https://www.nowcoder.com/questionTerminal/28c1dc06bc9b4afd957b01acdf046e69来源:牛客网
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?输出需要删除的字符个数。
输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出一个整数,代表最少需要删除的字符个数。
输入 | 输出 |
abcda | 2 |
2 |
import java.util.Scanner;
/**
* @author heye
* @date 2018年3月24日 上午10:50:21
* @version 1.0 */
public class Main{
public static void main(String[] args) {
Scanner c = new Scanner(System.in);
String string1 ="";
while(c.hasNext()) {
//输入字符串
string1= c.nextLine();
//输入字符串的倒序
String string2 = new StringBuffer(string1).reverse().toString();
char[] ds1 = string1.toCharArray();
char[] ds2 = string2.toCharArray();
int len = ds1.length;
//记录个数,空一行一列出来,int数组初始化均为0
int[][] arr = new int[len+1][len+1];
for(int i=1;i<=len;i++) {
for(int j = 1;j <=len ; j++) {
if(ds1[i-1] == ds2[j-1]) {
arr[i][j]= arr[i-1][j-1]+1;
}else {
arr[i][j] =Math.max(arr[i-1][j],arr[i][j-1]);
}
}
}
//最长公共子序列为arr[len][len],答案是删掉字符数
System.out.println(len-arr[len][len]);
}
}
}