您的位置:首页 > 其它

Leetcode 300:最长上升子序列

2019-03-26 16:45 363 查看

 

题目描述

给定一个无序的整数数组,找到其中最长上升子序列的长度。

示例:

输入: [code][10,9,2,5,3,7,101,18]
输出: 4 解释: 最长的上升子序列是 
[2,3,7,101],
它的长度是4。[/code]

说明:

  • 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
  • 你算法的时间复杂度应该为 O(n2) 。

进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

 

解题思路:

动态规划:

O(N^2)的状态很好定义:dp[i]表示以nums[i]结尾的最长子序列,状态转换方程为 dp[i] = max(1,max(dp[i-1],dp[i-2],....dp[0]))

上面dp[i]的定义复合一般定义状态的小套路(一般性的小套路见https://mp.csdn.net/postedit/88760391)。但是O(nlogn)的方法也一定要理解并掌握,因为面试的时候如果只写出O(N^2)面试官一定会让对其优化。直接设计O(nlogn)的状态可能一时先不到,但是可以从时间复杂度的形式逆向考虑,既然是O(nlogn),而且最外层循环不可能优化,那么只能优化内层循环为O(logn),完美知道二分查找是O(logn)的时间复杂度,但是要求待查找的序列排好顺序。也就是要求我们设计的dp[]数组的状态是排好顺序的。定义dp[i]表示长度为i+1的子序列最后元素的最小值,

  1. i=0  dp[0] = 10
  2. i=1  9<10 替换dp[0] = 9
  3. i=2 2<9    替换dp[0] = 2
  4. i=3 5>2    将5加入dp,dp[0] = 2, dp[1] = 5
  5. i=4 7>5    将7加入dp,dp[0] = 2, dp[1] = 5,dp[2] = 7
  6. i=5 101>7 将101加入dp,dp[0] = 2, dp[1] = 5,dp[2] = 7,dp[3] = 101
  7. i=6 18<101 替换dp[3] = 18

 

O(N^2)

[code]int lengthOfLIS(vector<int>& nums) {
int len = nums.size();
if(len <= 1) return len;
int dp[len] = {0},ans = 1;
for(int i=0;i<len;i++){
int j=i-1;
int tmp = INT_MIN;
while(j>=0){
if(nums[j] < nums[i]) tmp = max(tmp,dp[j]);
j--;
}
dp[i] = max(1,tmp+1);
ans = max(ans,dp[i]);
}
return ans;
}

O(NlogN)

[code]int lengthOfLIS(vector<int>& nums) {
int len = nums.size();
if(len <= 1) return len;
int dp[len] = {0},maxl = 1;
dp[0] = nums[0];
for(int i=0;i<len;i++){
int l = 0,r = maxl;
while(l < r){
int mid = l + (r-l)/2;
if(dp[mid]>=nums[i]) r = mid;
else l = mid + 1;
}
dp[l] = nums[i];
if(l == maxl) maxl++;
}
return maxl;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: