题目
求一个一维数组a[i]中的最长递增子序列的长度,如在序列1,-1,2,-3,4,-5,6,-7中,最长递增子序列长度为4,可以是1,2,4,6,也可以是-1,2,4,6。
算法思路
算法一(简单暴力)
/**
用b[]记录当前最长递增子序列长度,b[i]表示a[0,...,i]中的最长递增子序列长度;
求b[i],就是从后向前分析,第i个元素的最长递增子序列的长度要么是1(单独成一个序列),要么就是第i-1个元素之前的最长递增子序列加1
**/
public class LongestIncreasingSubsequence{
public static void main(String[] args) {
int a[]={1,-1,2,-3,4,-5,6,-7};//数组
int len = a.length;//数组长度
int b[]=new int[len];//b[i]表示a[0,...,i]中的最长递增子序列长度
for(int i=0;i<len;i++){//初始化为1
b[i]=1;
}
int max=1;//记录最大递增子序列长度
for(int i=1;i<len;i++){
for(int j=i-1;j>=0;j--){//寻找i-1前的最长子序列长度
if(a[i]>a[j]&&b[i]<b[j]+1){//更新最大值,作为i的最长子序列长度
b[i]=b[j]+1;
}
}
if(max<b[i]){
max=b[i];
}
}
System.out.println(max);
}
}
时间复杂度为o( n2 )
算法二(快速排序+最长公共子串)
不难理解,对于原数组所求的最长递增子序列,在数组按递增排序之后,也是有序数组的最长递增子序列。
比如a[]={1,-1,2,-3,4,-5,6,-7}
排序之后:a1[]={-7,-5,-3,-1,1,2, 4,6}
则a和a1的最长公共子序列是是1,2,4,6,也可以是-1,2,4,6。而这个也正是a数组的最长递增子序列
所以该算法分为两个步骤,先排序,得到数组a1,之后求两数组公共子序列。
时间复杂度o(nlogn)+o(
n2
)=o(
n2
)
算法三(二分查找)
/**
maxVal数组是记录最大递增子序列的数组,严格来说,其元素并不是最大递增子序列,但是其元素具有求解最大递增子序列长度的意义。
l是maxVal数组有效长度,也是最终求得最大递增子序列长度
算法估计难以用语言描述,但是可以举个例子:
a[]={1,-1,2,-3,4,-5,6,-7}
i=0,初始化:maxVal={1},l=1;
i=1,a[i]=-1<maxVal[l-1],则查找maxVal数组中是否存在a[i],如果不存在就用a[i]替换maxVal从0到l-1元素中第一个大于a[i]的元素,所以maxVal={-1}
i=2,a[i]=2>maxVal[l-1],则直接将a[i]加入maxVal中即maxVal[l++]=a[i],则maxVal={-1,2},l=2
i=3,a[i]=-3<maxVal[l-1],查找maxVal数组中是否存在a[i],如果不存在就用a[i]替换maxVal从0到l-1元素中第一个大于a[i]的元素,所以maxVal={-3,2}
i=4,a[i]=4>maxVal[l-1],则直接将a[i]加入maxVal中即maxVal[l++]=a[i],则maxVal={-3,2,4},l=3
i=5,a[i]=-5<maxVal[l-1],查找maxVal数组中是否存在a[i],如果不存在就用a[i]替换maxVal从0到l-1元素中第一个大于a[i]的元素,所以maxVal={-5,2,4}
i=6,a[i]=6>maxVal[l-1],则直接将a[i]加入maxVal中即maxVal[l++]=a[i],则maxVal={-5,2,4,6},l=4
i=7,a[i]=-7<maxVal[l-1],查找maxVal数组中是否存在a[i],如果不存在就用a[i]替换maxVal从0到l-1元素中第一个大于a[i]的元素,所以maxVal={-7,2,4,6}
所有过程结束,l就是最长递增子序列的长度为4
上面查找则是用简单的二分查找法,具体代码如下:
**/
public class LongestIncreasingSubsequence {
public static void main(String[] args) {
int a[]={1,-1,2,-3,4,-5,6,-7};
int len = a.length;
int maxVal[] = new int[len];
maxVal[0]=a[0];
int l=1;
for(int i=1;i<len;i++){
if(a[i]>maxVal[l-1]){
maxVal[l++]=a[i];
}else{
int pos = binSearch(a,0,l-1,a[i]);
maxVal[pos]=a[i];
}
}
System.out.println(java.util.Arrays.toString(maxVal));
System.out.println(l);
}
private static int binSearch(int[] a, int left,int right,int x) {
while(left<=right){
int mid = (left+right)/2;
if(a[mid]<=x){
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
}
时间复杂度o(nlogn)