Given a sequence of integers, find the longest increasing subsequence (LIS).
You code should return the length of the LIS.
For [5, 4, 1, 2, 3], the LIS is [1, 2, 3], return 3
For [4, 2, 4, 5, 3, 7], the LIS is [4, 4, 5, 7], return 4
public class Solution {
/**
* @param nums: The integer array
* @return: The length of LIS (longest increasing subsequence)
*/
/**
* state: lis[i] 表示前i个数字中,以第i 个数结尾的LIS中,有多少个数字
* function: lis[i] = max{lis[i],lis[j]+1 j<i && nums[j] <= nums[i] }
* 如果当前 lis[i]的值大于 lis[j]+1 的值, 则不变,否则
* lis[i] = lis[j]+1
* initialize: lis[0,,,n]=1
* 因为每个元素 最短序列起码可以是它自己。容易出错误的点是:
* 初始化的时候只把 lis[0]付值为1
* answer:max(lis[0,,,n])
*/
public int longestIncreasingSubsequence(int[] nums) {
// write your code here
if (nums == null || nums.length == 0){
return 0;
}
int l = nums.length;
int[] lis = new int[l];
for (int i = 0; i < l; i++) {
lis[i] = 1;
}
for (int i = 1; i < l; i++) {
for (int j = 0; j < i; j++){
if (nums[j] <= nums[i]) {
lis[i] = Math.max(lis[i], lis[j] + 1);
}
}
}
int res = 1;
for (int i = 1; i < l; i++) {
if (res < lis[i]) {
res = lis[i];
}
}
return res;
}
}
以上方法的时间复杂的为O(n^2)
另外一种方法是用binary search,时间复杂度可以达到O(nlogn)
for (i=1,,n){
}
LIS[i] 表示对于传入的序列s, 增长序列长度为 i 的所有子序列中,最后一个数最小的那个数字:
eg 对于序列 s = 6,7,18,19,4,12,13,11,1
长度为 3 的所有增长自序列有:(6,7,18)(7,18,19)(4,12,13)
这3个序列的最后一个数字为 18,19,13
最小的一个为13, 则 LIS[3]=13
initialize: 设 LIS[1,,n] 为无穷大
遍历 序列 s,每次找LIS 数组中 第一个比 s[ j ] 大的数,然后替换。这样搜索的时间是 O(nlogn)
for ( s[1,,n] ){
LIS[1] LIS[2] LIS[3] LIS[4] LIS[5] LIS[6] LIS[7] LIS[8] LIS[9]
∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞
6 6
7 7
18 18( 解释:当遍历到18时, LIS[1]=6, LIS[2]=7, LIS[3]= ∞ , LIS数组中 第一个比8大的是 LIS[3],则把8 付值给 LIS[3] )
19 19
4 4
12 12
13 13
11 11
1 1
}