题目的意思是在一个数组中,求出最长递增的一个序列长度。
以数组 arr = {4,2,3,1,5,6,4,8,9}; 为例:
先创建一个dp数组 ,用dp数组的下标来表示最长递增子序列的长度
程序执行顺序:
遍历arr数组
dp[1] = 4;
dp[1]=4>2 所以更新 dp[1] = 2
dp[1]=2<3 所以3加入dp dp[2] = 3
dp[2]=3>1 此时遍历dp数组 由于dp数组是递增排列的 找到第一个大于1的数 并更新该数 即 dp[1]=2>1 所以dp[1] = 1
dp[2] = 3 <5 所以 dp[3] = 5
dp[3] = 5<6 所以 dp[4] = 6
dp[4] = 6 >4 遍历dp数组 找到第一个大于4的数 即为dp[3] = 5 此时更新dp[3] = 4
.......(以此类推下标 即为最递增子序列的度)
/**
* @author wl
* @Data 2020-05-09 20:47
*/
public class LIS_最长递增子序列 {
public static void main(String[] args) {
int[] arr = {4,2,3,1,5,6,4,8,9};
System.out.println(Lcs(arr));
}
/**
* nlog(n)
* @param arr
* @return
*/
static int Lcs(int[] arr){
int[] dp = new int[arr.length+1];
dp[1] = arr[0];
int p = 1;
for (int i = 1; i < arr.length; i++) {
if (arr[i]>dp[p]){
dp[p+1] = arr[i];
p++;
}else{
//可以用二分法优化
/* for (int j = 0; j <= p; j++) {
if (dp[j]>arr[i]){
dp[j]=arr[i];
}
}*/
//优化后
int flag = erfen(dp,arr[i],0,p);
if (flag!=-1){
dp[flag] = arr[i];
}
}
}
return p;
}
static int erfen(int[]dp,int v,int l,int r){
while (l <= r){
int mid = (r+l)>>1;
if (dp[mid]>v){
r=mid;
}else {
l=mid+1;
}
if (l==r && dp[mid]>v)
return l;
}
return -1;
}
}