问题描述
给定两个数组,求出两个数组中公共的最长子序列以及子序列的长度
算法思路
假设有两个数组,array1={x1,x2,x3,x4…xm},array2={y1,y2,y3,y4,…yn},要找出他们的最长公共子序列,可以递归的进行定义,若是xm==yn,则找出array1[m-1]和array2[n-1]的最长公共子序列,然后加上xm即可;若是xm!=yn,找出array1[m-1]和array2[n]的的最长公共子序列和array1[m]和array2[n-1]的的最长公共子序列,取其中较大者即可。
令array[i][j] 记录序列xi和yj的最长公共子序列的长度,建立如下关系:
array[i][j]=0 (i==0||j==0)
array[i][j]=array[i-1][j-1]+1 (xi==yj)
array[i][j]=max{array[i-1][j],array[i][j-1]} (xi!=yj)
同时令position数组保存子序列的值,position数组满足如下关系
position[i][j]=1; (array1[i]==array2[j])
position[i][j]=2; (array1[i-1][j]>=array1[i][j-1])
position[i][j]=3;(array1[i-1][j]
public static Map<String,Object> getCommonSequenceLength(int[] array1,int[] array2){
int n=array1.length;
int m=array2.length;
int[][] array=new int[n][m];
int[][] position=new int[n][m];
for(int i=0;i<n;i++){
array[i][0]=0;
}
for(int j=0;j<m;j++){
array[0][j]=0;
}
for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
if(array1[i]==array2[j]){
array[i][j]=array[i-1][j-1]+1;
position[i][j]=1;
}else{
if(array[i-1][j]>=array[i][j-1]){
array[i][j]=array[i][j-1];
position[i][j]=2;
}else{
array[i][j]=array[i-1][j];
position[i][j]=3;
}
}
}
}
int max=array[0][0];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(max<array[i][j]){
max=array[i][j];
}
}
}
Map<String, Object> map=new HashMap<String, Object>();
map.put("length", max);
map.put("position", position);
return map;
}
构造子序列的值,当两者相等时,就可以输出即position[i][j]==1
public static void getCommonSequence(int i,int j,int[] array,int [][] position){
if(i==0||j==0){
return;
}
if(position[i][j]==1){
getCommonSequence(i-1, j-1, array, position);
System.out.print(array[i]+" ");
}else if(position[i][j]==2){
getCommonSequence(i-1, j, array, position);
}else{
getCommonSequence(i, j-1, array, position);
}
}