回到首页

最长递增子序列

方法一:动态规划。dp数组dp[i]指以nums[i]为结尾的最长递增子序列,dp[0]=1,当nums[i]>nums[j]时dp[i]取max(dp[i],dp[j]+1),结果$res=max_{i=0}^{n-1}dp[i]$。时间复杂度$O(n^2)$

方法二:贪心+二分查找。从nums按序构建递增子序列,遍历完构建的是最长递增子序列,递增子序列相应位置的元素尽可能地小,这样增长缓慢,到最大值时序列容纳的元素最多。遍历nums,设递增子序列d,其长度为len,d[0]=nums[0], len=1,当i>0时如果nums[i]>d[len-1],d[len++]=nums[i],否则,在d中执行二分查找,找到某位置j,使得d[j]<nums[i]<d[j+1],nums[i]替代d[j+1]。len即结果。时间复杂度$O(nlogn)$

判断数组是否存在三元递增子序列。使用方法二达到时间复杂度O(n),空间复杂度O(1)的效果。

大小为(n,2)的二维数组在第二维度的两个方向上递增排列的最大长度,设第二维度的两个方向分别是w,h,按照w升序h降序排列二维数组,求h上的最长递增子序列即为解。我想到二维数组需要排列整理,离解出题只差关键一步:h降序再求最长递增子序列,这个想法很妙,w相同时最多可选出一个h值构建题解,且不用单独考虑非得取相同w下h的最小值(使得递增子序列尽可能长)或最大值(递增子序列偏后面的部分可以取最大值,使得前面容纳更多的值)

n个二元数对中第一个数字总是比第二个数字小,求最长严格递增数对链。思路和求最长递增子序列差不多,递增的单个元素变为一个数对,粒度提高,数对[0]要比前一个数对[1]大。动态规划:dp[i]表示以pairs[i]为结尾的最长递增数对链长度;对每个元素来说,从前依次遍历确定dp[i],时间复杂度$O(n^2)$,记得排序!!!。贪心:不是乱贪心的,先做好准备再贪心;按pairs[1]的值升序排列pairs,按序只要满足pairs[i-1][1]<pairs[i][0]就拿取pairs[i],这个贪心过程构建出最长递增数对链

不重复列举出未排序数组的所有长度至少为2的非严格递增子序列:深度优先递归遍历数组列举子序列;此外,三个约束条件,不重复、长度至少为2、非严格递增;深度优先遍历中携带一个标志项last,表示当前构建的子序列的最后一个元素值;遍历时的元素值不小于last方可选择进入子序列,保证非严格递增;遍历时的元素值与last不相等方可不选择进入子序列并继续深度搜索,之所以遇到等于last的元素,在此处停止对该元素的深搜,是因为last已被选择,此时的元素不选择会与last不选择、此元素选择(此元素被选择的情况一定发生)重复(保证不重复的逻辑方法);最后列举出一个子序列,检查子序列的长度至少为2。

数组中最长严格递增子序列的个数:相比求最长递增子序列的长度,需额外声明记录i号元素为末尾的最长严格递增子序列长度的数组count,count[0]=1, count[1:]=0, 在数组dp遍历中,确定好dp[i]的值后,若dp[i]==1,则count[i]=1,否则若nums[j]<nums[i]且dp[j]+1==dp[i],即j号元素接上i号元素构成以i号元素结尾的最长递增子序列,则count[i]+=count[j]。求出dp[:]的最大值max,遍历dp,若dp[i]==max, res+=count[i],res即为解。

最长递增子数组的长度:res=1,cnt=1,遍历nums[1:],若nums[i]>nums[i-1],cnt++,否则res=max(res, cnt)且初始化cnt=1,遍历完后res=max(res,cnt),使得全部元素递增的数组的测试用例通过。

两个字符串S和T,求S中包含T为子序列的最短子字符串,若S产生的子序列不会有T,则返回空字符串。算法过程:包含sn个-1元素值的cur数组,记录T[0]==S[i]的i值,对T[1:]的每个字符T[j],记录T[j]==S[k]的,设定cur[k]=最近的子序列首元素位置,最后cur[k]!=-1的k满足S[k]==T.back(),而cur[k]的值就是候选子序列的首元素在S中的索引,在cur中从左到右挑选答案,设start=0,end=sn,如果cur[i]>=0且i-cur[i]<end-start,更新start=cur[i],end=i,注意计算子序列长度的算式应是i-cur[i]+1,但这里做的好处有二:标记该条件是否曾经成立,注意cur中若标明S含有T的子序列,则此条件必成立,因为最大的i==sn-1,最小的cur[i]==0;二是比较子序列之间的长度,都去掉了+1,且一次都没有进入循环的首条件,end还是sn,但进过一次循环的首条件,end绝对小于sn,依此判断有无子序列的最短字符串

参考链接:300. 最长递增子序列
334. 递增的三元子序列
354. 俄罗斯套娃信封问题
646. 最长数对链
491. 递增子序列
673. 最长递增子序列的个数
674. 最长连续递增序列
727. 最小窗口子序列

本文创建于2022.3.7/17.54,修改于2022.5.17/00.22

#dp #greed #binary_search