求一个数组的最长递增子序列(即不一定连续)
package suanfa.impover;
import java.util.Arrays;
/**
* 求一个数组的最长递增子序列(即不一定连续)
*/
public class LengthgestSubSequence {
/**
*用一个数组,count[i]:表示到第i位为止,最长的递增子序列的长度
* O(N2)
*/
public static int concrete(int [] a){
int [] count =new int [a.length];
for (int i=0;i<a.length;i++){
count[i]=1;
for (int j=i-1;j>-1;j--){
if (a[i]>a[j]&&count[j]+1>count[i]){
count[i]=count[j]+1;
}
}
}
return count[a.length-1];
}
/**
* 用一个变量来保存第i为之前的递增子序列的最大长度,来减少比较的次数
* O(N2)
*/
public static int concrete2(int [] a){
int maxL=0;
int [] count=new int[a.length];
for (int i=0;i<a.length;i++){
count[i]=1;
for (int j=i-1;j>-1;j--){
if (a[i]>a[j]&&count[j]+1>count[i]){
count[i]=count[j]+1;
}
if (count[i]>maxL){
maxL=count[i];
break;
}
}
}
return maxL;
}
/**
* 前面的方法在计算第i位时,不考虑前面i-1位的数。
* 现在考虑前i-1位的数:
* 用maxV[i]记录连续长度为i的序列中的最大值,当第 i+1个数的大于 最长序列中的最大值时,
* 则把该数并在该序列后面。
*
* 具体理解理解程序!!
* 此时时间复杂度任然为O(n2)
*/
static int fun1(int [] a){
int maxLen=1;
int [] maxV=new int[a.length+1];
maxV[0]=Integer.MIN_VALUE;
maxV[1]=a[0];
for (int i=1;i<a.length;i++){
int len=1;
// 寻找i前面的最长序列
int j=maxLen;
for (;j>-1;j--){
if (a[i]>maxV[j]){
len=j+1;
break;
}
}
if (len >maxLen){
maxLen=len;
maxV[len]=a[i];
}else if (a[i]>maxV[j] && a[i]<maxV[j+1]){
maxV[j+1]=a[i];
}
}
return maxLen;
}
/**
* 将上面寻找 i 前最长序列的 过程换成 二分查找:即找小于a[i]的最大maxV[j]
*
* 理解:i<j 时, a[i] 也必定小于 a[j]
*
* 时间复杂度:O(n*log2n)
*
*/
static int fun2(int [] a){
int [] maxV = new int[a.length+1];
maxV[0]=Integer.MIN_VALUE;
maxV[1]=a[0];
int maxLen=1;
for (int i=1;i<a.length;i++){
int len=1;
int key=a[i];
// 寻找i前的最长序列
int low=0,high=maxLen;
int mid=0;
while (low < high-1){
mid = low + (high-low)/2;
if (key > maxV[mid]){
low = mid +1;
}else {
high = mid-1;
}
}
if (key>maxV[high]){
mid=high;
len=high+1;
}else if (key>maxV[low]){
mid=low;
len=low+1;
}
if (len>maxLen){
maxLen=len;
maxV[len]=a[i];
}else if (a[i] > maxV[mid] && a[i]<maxV[mid+1]){
maxV[mid+1]=a[i];
}
}
return maxLen;
}
public static void main(String[] args) {
int [] a1={1,-1,2,-2,3,-3,4};
int [] a2={1,8,9,10,2,3,4,5,6,7};
System.out.println(Arrays.toString(a1));
System.out.println("max length is :"+fun2(a1));
}
}