题目:
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18]
,
The longest increasing subsequence is [2, 3, 7, 101]
, therefore the length is 4
. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
题意:
给定一个无序的整数数组,找到最长的递增子序列。算法应该在O(n^2)的时间复杂度内。返回的值只是最长子序列的长度,需要注意的是最长子序列可能不止一种组合。
Follow up:
是否能改进O(n2)的时间复杂度到O(nlogn)时间复杂度。
思路一:
使用动态规划,使用数组res[i]记录到下标i时最长的上升序列,时间复杂度为O(n2),将num数组中的每个值与之前的所有值进行对比,如果比它小的值,在小的值最长序列上加1;
nums | 10 | 9 | 2 | 5 | 3 | 7 | 101 | 18 |
res | 1 | 1 | 1 | 2 | 2 | 3 | 4 | 4 |
代码:java版:33ms
public class Solution { public int lengthOfLIS(int[] nums) { int[] res = new int[nums.length]; int len = 0; for (int i=0; i<nums.length; i++) { res[i] = 1; for (int j=0; j<i; j++) { if (nums[i] > nums[j]) res[i] = Math.max(res[i], res[j]+1); } len = Math.max(len,res[i]); } return len; } }
思路二:
使用二分搜索替代上面的内循环,将时间复杂度由O(n2)提升到O(nlogn),使用dp数组记录当前最长上升序列的值。注意Arrays.binarySearch函数的返回值特点。
起点 | Len | X值 | Dp数组值 | Arrays.binarySearch结果值 |
0 | 0 | 10 | 0 0 0 0 0 0 0 0 | -1 |
0 | 1 | 9 | 10 0 0 0 0 0 0 0 | -1 |
0 | 1 | 2 | 9 0 0 0 0 0 0 0 | -1 |
0 | 1 | 5 | 2 0 0 0 0 0 0 0 | -2 |
0 | 2 | 3 | 2 5 0 0 0 0 0 0 | -2 |
0 | 2 | 7 | 2 3 0 0 0 0 0 0 | -3 |
0 | 3 | 101 | 2 3 7 0 0 0 0 0 | -4 |
0 | 4 | 18 | 2 3 7 101 0 0 0 0 | -4 |
代码:java版:2ms
public class Solution { public int lengthOfLIS(int[] nums) { int[] dp = new int[nums.length]; int len = 0; for (int x : nums) { int i = Arrays.binarySearch(dp, 0, len, x); if (i<0) i = -(i + 1); dp[i] = x; if (i == len) len++; } return len; } }
思路三:
利用std::lower_bound函数获取到序列应该插入的下标值,如果返回的下标值处于res的末尾,则说明比res数组尾数大,是递增,则将该数添加到res数组之后,如果小于res数组末尾值,则覆盖更新该处的值。
代码:7ms
class Solution { public: int lengthOfLIS(vector<int>& nums) { vector<int> res; for(int i=0; i<nums.size(); i++) { auto it = std::lower_bound(res.begin(), res.end(), nums[i]); if(it==res.end()) res.push_back(nums[i]); else *it = nums[i]; } return res.size(); } };