LIS(Longest Increasing Subsequence):最长上升子序列
这里分两种情况来看:
- 子序列严格递增(即子序列中不能存在相等)
- 子序列非降(即子序列中可以存在相等)
对于序列:a[1] , a[2] , a[3] , … , a[N]
一、动态规划(DP) 时间复杂度:O(N2)
- 子序列严格递增:dp[i] = max{1 , dp[j]+1} ( j<i && a[j]<a[i] )
- 子序列非降:dp[i] = max{1 , dp[j]+1} ( j<i && a[j]<=a[i] )
即找到能衔接在a[i]前最大的dp[j] (a[j]能衔接在a[i]之前)
二、二分法 时间复杂度:O(N*logN)
创建一个数组d(下标从1开始): 维护LIS的长度
一个变量len: 表示当前d的长度,d[len]正好是LIS的末尾元素,最终得到的len即为答案。
初始令 d[1]=a[1],len=1; 再从i=2开始遍历a。
注意,数组d中仅仅只是长度与LIS相同,本身并不是一个LIS(因为插入后前后顺序被打乱了),只能得到LIS的长度,若要得到LIS,还需要记录路径。
详见—> https://blog.csdn.net/Ratina/article/details/98875528
1. 子序列严格递增
当d[len] < a[i]:说明a[i]能接在d[len]后面,长度增加,直接 d[++len] = a[i];
否则,找到 d(LIS)中第