题目链接:https://leetcode.com/problems/longest-increasing-subsequence/
题目:
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?
思路:
1、简单动态规划,c[i]表示从0~i的数组中 包含nums[i]的LIS,状态转移方程:c[i]=max{c[j]+1} ,j<i且nums[i]>nums[j],时间复杂度为O(n^2)
2、动态规划加二分搜索,b[i]表示长度为i的LIS最后一个元素大小,end是b数组最后一个元素也就是当前LIS的下标。 对每个元素进行如下判断:
若nums[i]>b[end],则更新LIS,否则二分搜索b数组比nums[i]元素大的最小位置idx,此时b[idx]>nums[i]>b[idx-1] 更新idx位置,因为此时同样长度的子串,包含nums[i]的要比包含b[idx]要小。 时间复杂度O(nlogn)。
算法:
1、
[java] view
plain copy
- public int lengthOfLIS(int[] nums) {
- if (nums.length == 0)
- return 0;
- int c[] = new int[nums.length];// c[i]表示从0~i 以nums[i]结尾的最长增长子串的长度
- c[0] = 1;
- int maxLength = 1;
- for (int i = 1; i < nums.length; i++) {
- int tmp = 1;
- for (int j = 0; j < i; j++) {
- if (nums[i] > nums[j]) {
- tmp = Math.max(c[j] + 1, tmp);
- }
- }
- c[i] = tmp;
- maxLength = Math.max(maxLength, c[i]);
- }
- return maxLength;
- }
2、
[java] view
plain copy
- public int lengthOfLIS(int[] nums) {
- if (nums.length == 0)
- return 0;
- int b[] = new int[nums.length + 1];// 长度为i的子串 最后一个数最小值
- int end = 1;
- b[end] = nums[0];
- for (int i = 1; i < nums.length; i++) {
- if (nums[i] > b[end]) {// 比最长子串最后元素还大,则更新最长子串长度
- end++;
- b[end] = nums[i];
- } else {// 否则更新b数组
- int idx = binarySearch(b, nums[i], end);
- b[idx] = nums[i];
- }
- }
- return end;
- }
- /**
- * 二分查找大于t的最小值,并返回其位置
- */
- public int binarySearch(int[] b, int target, int end) {
- int low = 1, high = end;
- while (low <= high) {
- int mid = (low + high) / 2;
- if (target > b[mid])
- low = mid + 1;
- else
- high = mid - 1;
- }
- return low;
- }