牛课网--最长递增子序列详解
Posted cyx-garen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛课网--最长递增子序列详解相关的知识,希望对你有一定的参考价值。
最长递增子序列
求给定一个数组中,最长递增子序列的长度
(子序列,可以不连续 子数组,需要连续)
Eg: arr={2,1,6,4,5,2,7,4} 最长递增子序列为 {2,4,5,7} 长度为4
解法一 O(n2)
思路:
- 生成辅助数组temp,temp[i]代表以arr[i]结尾的情况下的最大子序列长度
- 设置temp[i]时,比较arr[i],遍历前方所有比arr[i]小的数,在其集合的最大temp值上加一
缺点:
在思路(2)中需要遍历arr数组的前方所有比arr[i]小的数,为O(n),整体为O(n2)
代码:
public int[] maxSize() { int[] arr={2,1,6,4,5,2,7,4}; int[] temp=new int[arr.length]; temp[0]=1; int max; for(int i=1;i<arr.length;i++){ max=0; for(int j=0;j<i;j++){ if(arr[j]<arr[i]&&max<=temp[j]) max=temp[j]; } temp[i]=max+1; } return temp; }
解法二 O(nlogn)
是对解法一的思路(2)中的改进,使用二分法将复杂度降低
思路:
- Temp存在有效区的概念,即只在一定区间内数据可以存放
- Temp[i]指的是在有效区中,长为i+1的最长子序列的最小末尾值
Temp数组的概念与解法一中有所不同(这里比较难理解)
举个例子: temp[1]=6代表的是长度为1+1=2的最长子序列的最小末尾值为6 ,此时若是继续遍历arr,发现存在子序列长度为2但是末尾值小于6的则会替换(2,1,6,2 1,6->1,2),这样做的意义是在于永远保持temp数组的值的最小,以便后续增加
Arr : 2 1 5 7 3 2->1->1,5->1,5,7->1,3,7
1,5,7->1,3,7 意味着遍历到目前为止,长度为2的子序列可以以5结尾,也可以以3结尾,但是为了统计后续的最大值,替换为3结尾的子序列,在此基础上增加
注意:此时不会影响到前面已经统计的, 1,5,7->1,3,7, 7结尾的最长子序列长度依然是3(子序列为1,5,7),
后面数字为2 1,3,7->1,2,7 长度为2的子序列最小末尾为2 1,2
后面数字为9 1,2,7->1,2,7,9 长度为4的子序列最小末尾为9 1,5,7,9(这个想清楚就理解了)
代码:
//arr>temp,往后 arr<temp,替换 public int[] maxSizeTwo() { int[] arr={2,1,6,4,5,2,7,4}; int[] temp = new int[arr.length]; int left=0,right=0,count=0,mid; temp[0]=arr[0]; for(int i=1;i<arr.length;i++){ right=count; while(left<right){ mid=(right+left)/2; if(arr[i]<temp[mid]){ right=mid-1; } else left=mid+1; } if(temp[left]<arr[i]){ count++; temp[left+1]=arr[i]; } else temp[left]=arr[i]; } return temp; }
以上是关于牛课网--最长递增子序列详解的主要内容,如果未能解决你的问题,请参考以下文章
牛客Top200---最长递增子序列(求子序列+长度 画图详解java)
代码随想录算法训练营第五十二天 | 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组