最长上升子序列的贪心二分解法证明

最长上升子序列是一个经典的动规问题,复杂度为On^2。可以通过贪心+二分优化为Onlgn复杂度,本文提供一个证明思路

注意,贪心法求最长上升子序列只能求长度

贪心思路:

维护一个最长上升子序列,尽量使这个上升子序列的结尾元素尽可能小,同样是上升子序列,结尾元素越小,越有产生更长子序列的趋势。即维护一个原序列中,结尾元素最小的最长上升子序列。

实现方法:

维护一个数组,在遍历序列元素时,将该序列元素与第一个大于该序列元素的数组元素替换

证明:

若在总长度为n的序列的前k个元素中,产生的最长子序列长度为len,最长子序列个数为lis_nums,那么这lis_nums个长度为len最长子序列中,结尾元素最小的最长子序列一定比其他的最长子序列更有可能堆叠更长的子序列,我们现在就使用一个简单的数组来维护当前所有最长子序列中结尾元素最小的最长子序列;

case1:当遍历下一个序列元素时,此元素大于数组的末尾元素,即最长子序列长度增长的情况,则将此元素增加到数组,成为新的数组末尾元素,最长上升子序列长度为len+1

case2:(理想的最长上升子序列数组维护情况)即下一个序列元素,小于数组末尾元素,但大于数组的倒数第二个元素,此时将数组末尾元素替换为下一个序列元素即可(即替换到数组中第一个大于它的元素)。如数组元素为 1 3 6,下一个序列元素为4,那么将1 3 6替换为1 3 4,显然 1 3 4比 1 3 6更有可能产生更优的长度

case3:当下一个序列元素不属于case1和2的情况,即小于数组的最后两个元素,此时的数组维护的仍是当前最优的最长上升子序列,此序列元素不会造成任何影响

case3.1 若当前数组维护的最长上升子序列,在整体上也是最优的,也就是后面遍历所有序列元素后,增长的元素也是基于这个子序列,那么后续的增长跟此数组中的末尾元素有关系,跟数组末尾之前的元素无关。此时,遍历的下一个序列元素和此维护数组除了末尾元素之外的元素,都是无关紧要的(对于最长上升子序列的长度来说)。
那我们就把该序列元素,替换到数组元素中第一个大于它的元素,不会改变末尾元素,如果改变了那就是case2了,矛盾。 那为啥这么做呢,不这么做可以吗? 可以,完全没问题,只是为了操作统一,方便

case3.2 若当前数组维护的上升子序列在整体上不是最优的(注意当前仍是最优的),假设数组的改变正是在遍历的下个序列元素num,那么我们就要把此序列元素放到数组中正确的位置,那么它正确的位置是哪个呢?显然数组中比num小的元素肯定也是在最终num所在的序列里,将num放到比它小的元素之后,即第一个比它大的元素之前。那之后的错的元素怎么办?我们说了num是最优的,那么新的序列会基于num产生,即大于num,肯定小于数组中大于num的数,否则若大于数组中大于num的数,那么就产生了更长的上升子序列,而且顺序错误了,num之前的序列在num后,矛盾

说明,假设数组元素是 m1 m2 m3 m4,后续序列元素是num1,num2,num3,num4,最终最优情况是m1,num1,num2,num3,num4
那么此时遍历到num1,数组变为m1,num1,m3,m4
m3一定是大于num2的,若否,则m3>num1,m3<num2,那么最终最优情况改变,矛盾。那么在遍历到num2时重复我们case3.2的操作,会将m3,m4替换到正确序列,正确答案产生。

此时当前的维护的数组在长度是正确的,元素是错误的,所以贪心法严格来说只能求解长度。过程中会不可避免的出现错误序列

case3.3 若当前数组维护的上升子序列在整体上不是最优的),假设数组的改变也不是在遍历的下个序列元素,此时怎么处理呢࿱

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值