给一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
示例 2:
输入:nums = [0,1,0,3,2,3]
输出:4
示例 3:
输入:nums = [7,7,7,7,7,7,7]
输出:1
提示:
1 <= nums.length <= 2500
- <= nums[i] <=
进阶:
可以设计时间复杂度为 O() 的解决方案吗?
能将算法的时间复杂度降低到 O(n log(n)) 吗?
下面示例方法 getLISLength3 是 O() , getLISLength2 和 getLISLength 是O(n log(n)),但实际执行时间 getLISLength2 应该会更快一点。
package com.loo;
import java.util.HashMap;
import java.util.Map;
public class LongestIncreaseSequence {
public static void main(String[] args) {
int[] arr = new int[] { 10,9,2,5,3,7,101,18 };
int[] arr2 = new int[] {0,1,0,3,2,3};
int[] arr3 = new int[] {5,4,3,2,1,0};
int[] arr4 = new int[] {3 , 3, 3, 3, 3};
System.out.println(getLISLength(arr2));
System.out.println(getLISLength2(arr));
System.out.println(getLISLength3(arr));
}
public static int getLISLength3(int[] arr) {
int length = 0;
if (arr == null || arr.length == 0) {
return length;
}
int[] dp = new int[arr.length];
int len = arr.length;
int result = 1;
dp[0] = 1;
for (int i=1;i<len;i++) {
dp[i] = 1;
for (int j=0;j<i;j++) {
if (arr[i] > arr[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
result = Math.max(result, dp[i]);
}
return result;
}
public static int getLISLength2(int[] arr) {
int length = 0;
if (arr == null || arr.length == 0) {
return length;
}
int[] nums = new int[arr.length];
int len = arr.length;
for (int i=0;i<len;i++) {
if (i<arr.length-1 && arr[i] == arr[i+1]) {
continue;
}
int index = getSearchBinary(nums , arr[i] , length);
if (index == -1) {
continue;
} else {
nums[index] = arr[i];
length = length > index ? length : ++length;
}
}
// System.out.println(Arrays.toString(nums));
return length;
}
public static int getSearchBinary(int[] arr , int target , int length) {
int left = 0;
int right = length - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (target == arr[mid]) {
return -1;
} else if (target > arr[mid]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
public static int getLISLength(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
Map<Integer , Integer> map = new HashMap<Integer , Integer>();
map.clear();
for (int i=0;i<arr.length;i++) {
if (i<arr.length-1 && arr[i] == arr[i+1]) {
continue;
}
int index = getSearchBinary(map , arr[i]);
if (index == -1) {
continue;
}
map.put(index, arr[i]);
}
// System.out.println(map);
return map.size();
}
public static int getSearchBinary(Map<Integer , Integer> map , int target) {
int left = 0;
int right = map.size() - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (target == map.get(mid)) {
return -1;
} else if (target > map.get(mid)) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
}