首先先来介绍一下最长子序列是什么
按照我的理解,最大子序列首先是两个串中相同的字符组成的,在两个字符串中,相同的字符可以不连续,但是必须字符的下标在字符串中是一次递增的。
举个简单的例子:
String “abdcegs”;
String “wbcasq”;
在这两个串中子序列有“as”,“bcs‘’
最大子序列为“bcs”
这种题我一共遇到两个解法,现在分享出来
第一种解法:递归解决
解法思路:
首先判断两个字符串的第一个字符是否相等
如果相等,则求两个去掉第一个字符的的子序列+1;
如果不相等,则求(去掉第一个字符的第一个字符串与第二个字符串的子序列)和(第一个字符串与去掉第一个字符的第二个字符串的子序列)
代码实现(java)
public static int f(String s1, String s2) {
if(s1.length()==0||s2.length()==0)
return 0;
if(s1.charAt(0)==s2.charAt(0))
return f(s1.substring(1),s2.substring(1))+1;
else
return Math.max(f(s1.substring(1),s2),f(s1,s2.substring(1)));
}
解法二:动态规划
解法思路:
注意:每次字符相同时,需要判断 矩阵[当前位置y轴-1][当前位置x轴-1]的最大值+1;
代码实现(java)
public static int f(String s1, String s2) {
int[][] s=new int[s1.length()+1][];
for(int i=0;i<s.length;i++){
s[i]=new int[s2.length()+1];
}//初始化二维数值
for(int i=1;i<s.length;i++){
for(int m=1;m<s[i].length;m++){
if(s1.charAt(i-1)==s2.charAt(m-1)){
s[i][m]=f1(s,i,m)+1;
}
}
}
return f1(s,s.length,s[0].length);
}
public static int f1(int[][] s,int n,int m){//找出矩阵[n-1][m-1]的最大值;
int max=0;//记录最大值
for(int j=0;j<n;j++){
for(int k=0;k<m;k++){
if(max<s[j][k]){
max=s[j][k];
}
}
}
return max;
}
对于第二种解决思路的优化:
当前第二种解决思路,每次判断字符相等后,又要进入两层循环去找最大值。
可以将两层循环改为一层
解决方案
定义一个数组i[ ];数组i[ ]是存放对应横下标位置每次改变的值
代码实现(java)
public static int f(String s1, String s2) {
int[][] s=new int[s1.length()+1][];
for(int i=0;i<s.length;i++){
s[i]=new int[s2.length()+1];
}//初始化二维数值
int[] c=new int[s2.length()+1];//!改变的地方
for(int i=1;i<s.length;i++){
for(int m=1;m<s[i].length;m++){
if(s1.charAt(i-1)==s2.charAt(m-1)){
s[i][m]=f1(c,m)+1;//!改变的地方
if(c[m]<s[i][m]){//!改变的地方
c[m]=s[i][m];
}
}
}
}
return f1(c,s[0].length);
}
public static int f1(int[] s,int m){//找出数组c[m-1]的最大值 ! !改变的地方
int max=0;//记录最大值
for(int j=0;j<m;j++){//!改变的地方
if(max<s[j]){
max=s[j];
}
}
return max;
}
矩阵图与上面一样
对以上算法再进行优化
去f1( )函数
思路:当判断字符不等后与(横坐标-1)和(纵坐标-1)的最大值相等
这样每次相等时,坐标(x,y)的值= 坐标(x-1,j-1)的值+1
public static int f(String s1, String s2) {
int[][] s=new int[s1.length()+1][];
for(int i=0;i<s.length;i++){
s[i]=new int[s2.length()+1];
}//初始化二维数值
for(int i=1;i<s.length;i++){
for(int m=1;m<s[i].length;m++){
if(s1.charAt(i-1)==s2.charAt(m-1)){
s[i][m]=s[i-1][m-1]+1;//!改变的地方
}else{//!改变的地方
int max=Math.max(s[i][m-1], s[i-1][m]);
s[i][m]=max;
}
}
}
return s[s.length-1][s[0].length-1];//改变的地方
}
以上就是我的所有见解,望斧正。
如果有志同道合的朋友可以一起来讨论聊天。