标签:查找 == lse 最长上升子序列 detail targe public 规划 注意
Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Input:[10,9,2,5,3,7,101,18]
Output: 4 Explanation: The longest increasing subsequence is[2,3,7,101]
, therefore the length is4
.
Note:
Follow up: Could you improve it to O(n log n) time complexity?
非常经典的一道动态规划题目,常用解法有两个
1、暴力搜索
时间复杂度O(N^2),空间复杂度O(N),f[i]表示以num[i]结尾的上升子序列的长度,外层循环遍历整个序列,复杂度O(n),内层循环则从第一个数遍历到外层循环的数字(不含)为止,转移方程为f[i] = max(f[i],f[j]+1)代码如下:
1 class Solution { 2 public: 3 int lengthOfLIS(vector<int>& nums) { 4 if (nums.size() == 0) 5 return 0; 6 vector<int> v; 7 int len = 1; 8 for (int i = 0; i < nums.size(); i++) 9 { 10 v.push_back(1); 11 for (int j = 0; j < i; j++) 12 if (nums[j] < nums[i]) 13 v[i] = max(v[i], v[j]+1); 14 if (v[i] > len) 15 len = v[i]; 16 17 } 18 return len; 19 } 20 };
2、二分搜索
时间复杂度O(N*logN),空间复杂度O(N),我们可以用一个数组,来记录当前已经形成的递增子序列,该数组一定是单调不减的,我们所希望的是末尾的数字尽量小,这样才会使得更多的数字有机会加入进来。外层循环需要遍历整个序列,内层循环则利用有序性进行二分查找,找到该数字在我们定义的数组中的位置,然后更新,最终返回该数组的长度即可,但是这么做要注意我们只保证长度是正确的,不保证该数组是一个最长上升子序列。
代码如下:
1 class Solution { 2 public: 3 int lengthOfLIS(vector<int>& nums) { 4 if (nums.size() == 0) 5 return 0; 6 vector<int> res; 7 res.push_back(nums[0]); 8 for (int i = 0; i < nums.size(); i++) 9 { 10 int left = 0, right = res.size()-1; 11 if (nums[i] > res.back()) 12 res.push_back(nums[i]); 13 else 14 { 15 while (left < right) 16 { 17 int mid = (left + right) / 2; 18 if (res[mid] < nums[i]) 19 left = mid + 1; 20 else 21 right = mid; 22 } 23 res[right] = nums[i]; 24 } 25 } 26 return res.size(); 27 } 28 };
易错点:6,7行,可以利用c++11新特性写成 res{nums[0]},但是千万别错写成res(nums[0])
参考链接:
https://www.cnblogs.com/lsgxeva/p/7787245.html
http://www.cnblogs.com/grandyang/p/4938187.html
https://www.cnblogs.com/GodA/p/5180560.html
https://blog.csdn.net/George__Yu/article/details/75896330
LeetCode 300. Longest Increasing Subsequence
标签:查找 == lse 最长上升子序列 detail targe public 规划 注意
原文地址:https://www.cnblogs.com/dapeng-bupt/p/9746259.html