面试题学习总结--(1)最长递增子序列及其进阶版

本系列是看了牛课网老师左程云http://www.nowcoder.com/live/11的BAT面试算法精品课的学习记录,我争取用我能做到的最容易理解的方式用文字表达出来,欢迎一起学习~

1. 最长递增子序列O(n^2)版

例如:求 2 1 6 4 5 2 7 4 这8个元素的最长递增子序列的长度是多少?

无脑dp:
  • 1.用h[i],记录第i个位置的最长子序列的个数,例如h[7]就是上述问题的解。
  • 2.h[i+1],通过比较前面i个的数值与当前数值的大小,如果前面的那个数k比当前的数小,那么当前h[i+1]就可以为h[k]+1,遍历完取最大值即可,例如h[0]=1,h[1]=1表示前面一个数 2 或者俩个数 2 1的最长递增子序列的个数都为1,那么h[2],由于6>1,2,那么h[2]可以为h[0]+1,也可以为h[1]+1,总之取最大值即可。
  • 3.由于每查看一个数,都要把它前面所有的数都比较一番,查看玩所有的数后总代价为O(n)。
无脑dp代码

2.最长递增子序列O(nlogn)版

还是求 2 1 6 4 5 2 7 4 这8个元素的最长递增子序列的长度是多少?

有脑dp:
  • 1.假设用一个数列h[i]来保存这“最完美” 状态的最长递增子序列,先来讲”最完美“版最长递增子序列怎么跟新的好了:
    原则:初始为第一个元素h={2},之后的每个元素,找到h中第一次比它大的元素并替换它,如果没有则加在后面。

    • 1.检查到2: h[]={2}
    • 2.检查到1:h[]={1}
    • 3.检查到6:h[]={1,6}
    • 4.检查到4:h[]={1,4}
    • 5.检查到5:h[]={1,4,5}
    • 6.检查到2:h[]={1,2,5}
    • 7.检查到7:h[]={1,2,5,7}
    • 8.检查到4:h[]={1,2,4,7}
  • 2.那么我们输出h的最大的元素个数4即使答案,为什么呢?

    • 1.事实上,最长递增子序列应该是1,4,5,7。其实从上述第5步时,我们也可以稍微看出一点1,4,5的影子,那么为啥来了个2就把4替换了呢?(看第6步和第5步的差别 )替换有啥用处?以及替换后会影响最长递增子序列个数的结果吗?
    • 2.第6步和第5步的差别,为啥来了个2就把4替换了?这里,h[0,1]={1,4}变为h[0,1]={1,2}表示,在还未检查下一个之前,长度为2(俩个元素)的最小的组合为{1,2}(我们可以查看原数列,1,2和1,4长度为2的递增子序列都是存在的,最小的为1,2),这样就可以给后面再来的数字提供更大的空间,即h[i]表示递增子序列长度为i+1时,最后一个数字能渠道的最小值的情况,可以一直更新,为后面来的数字提供空间。
    • 3.替换后会影响最长递增子序列个数的结果吗?我们只是替换第一个比它大的数,为后面的可能留空间,并不会影响最长的结果。

2.最长递增子序列进阶O(nlogn)版

把元组(1,2)(3,7)(4,3)(5,4)(6,5),摞起来,(a1,b1),(a2,b2)满足a1<a2,b1<b2即可把第二个摞在第一个上面,求最长能够摞几个要求时间复杂度为O(nlogn)?

解决办法
  • 1.先根据a,按从小到大排序,如果a相同,b则按照从大到小排序,然后每个元组只取b的值,将所有取出来的b根据上述排序排成一列,那么这个新数列的最长递增子序列就是原问题的解
  • 2why?,首先先按a从小到大排序,解决了后面的a比前面的a大的问题,再者,对于b,如果不从大到小排列,那么b最开始就取一个很大的值,那么就可能把一些可能情况排除掉,例如(1,1)(2,9)|(3,4)(2,3)和(1,1)(2,3)(3,4)|(2,9),如果b不按从大到小,第一种,只能摞前俩个进去,后面就不能放上去了,第二种,给后面留了空间,就可以把(3,4)也摞进去了,并且不会影响(1,2)(2,9)这种情况的存在,万一这种也可能时最长的一种是吧?
  • 3.总之一句话,a从小到大排列解决了a的问题,b从大到小排列,决解了所有可能的情况,并给后面的一个个b留足了空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值