对于一个数字序列,请设计一个复杂度为O(nlogn)的算法,返回该序列的最长上升子序列的长度,这里的子序列定义为这样一个序列U1,U2...,其中Ui < Ui+1,且A[Ui] < A[Ui+1]。
给定一个数字序列A及序列的长度n,请返回最长上升子序列的长度。
import java.util.*;
public class AscentSequence {
/*最长递增子序列 LIS
* 方法一:先排序 在求最长公共字串 n2
* 方法二:DP[i] 以i为结尾的最长公共子序列长度 n2
* 方法三:help[i] n个长度为i的子序列中末尾最小的值
* 因为最长的LIS肯定可以由n个最短的LIS中末尾最小的那个序列依次叠加形成
* 长度为5的肯定可以由N个长度为4的中末尾最小的加1组成
* 长度为4的肯定可以由N个长度为3的中末尾最小的加1组成
* 长度为3的肯定可以由N个长度为2的中末尾最小的加1组成
* 长度为2的肯定可以由N个长度为1的中最小的加1组成
* 例如 2 1 5 3 6 4 8 9 7
* i 1 2 3 4 5
* help[i] 2 5 6 8 9
* 1 3 4 7
* help是有序的可以二分法logN 总复杂度NlogN*/
public int findLongest(int[] A, int n) {
if (A==null||n<=0){
return 0;
}
int[] help = new int[n];
int i=0;
help[i] = A[0];
for (int j = 1; j < n; j++) {
if (A[j]>help[i]){
i++;
help[i] = A[j];
}else {
if (A[j]<=help[0]){
help[0]=A[j];
}else {
int k = BinFind(help,0,i,A[j]);
help[k] = A[j];
}
}
}
return i+1;
}
public int BinFind(int[] help,int low,int high,int value){
while(low<=high){
int mid = low + ((high-low)>>1);
if (help[mid]==value){
return mid;
}
else if(help[mid]<value){
low = mid+1;
}else{
high = mid-1;
}
}
return low;
}
}
题目来源:http://www.nowcoder.com/practice/585d46a1447b4064b749f08c2ab9ce66?rp=3&ru=/activity/oj&qru=/ta/2016test/question-ranking
参考:http://blog.csdn.net/dongmianshu/article/details/5954992