什么是序列DP
序列dp是一类最长,最多的子序列的相关问题。 状态转移方程中 dp[i] 表示前i个元素a [0],a [1],…a [i-1]的某种性质, 坐标型 dp 状态转移方程中f [i]表示以元素a [i]结尾的某种性质。
LIS
最长递增子序列的长度
最长递增子序列的个数
class Solution {
public int findNumberOfLIS(int[] nums) {
// 如果是n2的方法,就是暴力dp
// 研究一个nlogn的方法 dp.get(i).get(j) 表示长度为i的第j种可能。
// 这里需要注意,如果是从前往后遍历的话,其实很容易发现,这个dp.get(i)一定是单调不增的,否则一定可以增加长度
// cnt[i][j] 是前缀和的思想,表示长度为i的时候,前j个元素作为结尾的全部可能数量
// 当我们遍历到某个数字的时候,查看dp每个list的最后一个数字(因为是最小的),如果大于,说明可以这个list里面起码有小于的当前数字的。假设是k
// 然后我们可以二分的找到边界p,并且用newadd = cnt.get(k).get(size()-1) - cnt.get(k).get(p)
// 最后在dp.get(k+1).add(nums[i]) cnt.get(k+1).add(last+)
List<List<Integer>> dp = new ArrayList<>();
List<List<Integer>> cnt = new ArrayList<>();
int n = nums.length;
for(int i = 0;i<n;i++){
int k = findList(dp, nums[i]);
int newadd = 1;
if (k >= 0){
int p = findInList(dp.get(k), nums[i]);
int size = cnt.get(k).size();
newadd = cnt.get(k).get(size-1)-cnt.get(k).get(p);
}
if(k == dp.size()-1){
dp.add(new ArrayList<Integer>());
cnt.add(new ArrayList<Integer>());
cnt.get(k+1).add(0);
dp.get(k+1).add(nums[i]);
cnt.get(k+1).<