问题描述
中文简单解释:求一个一维数组arr[i]中的最长递增子序列的长度,如在序列1,-1,2,-3,4,-5,6,-7中,最长递增子序列长度为4,可以是1,2,4,6,也可以是-1,2,4,6。
思路分析
最简单的思路是动态规划,数组a表示输入的数组,用一个数组dp记录子串每一位的最长递增子串长度,采用公式
dp[i]=max (dp[j],0)+1 st:j
遍历一遍复杂度为O(n),即外层循环。求max得过程又需要遍历一遍,即内部循环。所以复杂度为o(n*n)。聪明的你一定可以很快实现这个算法,我的代码可见下一个部分“代码实现”。
那这里用7行代码解决该问题的思路是怎样的呢?好奇的你可以先去下方看一下代码思考一番。
先夸一下这个代码的性能:不仅代码简洁,而且可以实现复杂度为o(nlgn)哦~ 优化时间复杂度的关键在于第二个循环,即内部循环,可以利用二分查找的思路使得复杂度降到o(lgn),而我的代码用了java中的集合框架treeSet,查找的过程不需要自己实现,但我们可以知道他的复杂度为o(logn)。使用这个框架是缩短代码行数的秘诀。
接下来我们看看具体思路:
可以用二分查找优化第二个循环:
//待续
代码实现
复杂度为o(n*n)
public int lengthOfLIS(int[] nums) {
int len=nums.length;
if(len==0) return 0;
int max[]=new int[len];
max[0]=1;
for(int i=1;i
{
int maxSub=0,maxPos=0;
for(int j=0;j
{
if(nums[j]
if(max[maxPos]
maxPos=j;
maxSub=max[maxPos];
}
}
max[i]=maxSub+1;
}
int maxLen=1;
for(int i=1;i
{
if(max[i]>maxLen) maxLen=max[i];
}
return maxLen; }
复杂度为o(nlgn)
public int lengthOfLIS (int[] nums) {
TreeSet set = new TreeSet<>();
for(int i : nums) {
Integer ceil = set.ceiling(i);
if(null != ceil) {set.remove(ceil); }
set.add(i); }
return set.size();}