【演算法】最長遞增子序列的長度
阿新 • • 發佈:2019-02-09
題目
求一個一維陣列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(
演算法二(快速排序+最長公共子串)
不難理解,對於原陣列所求的最長遞增子序列,在陣列按遞增排序之後,也是有序陣列的最長遞增子序列。
比如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( 2
演算法三(二分查詢)
/**
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)