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?
这道题还算简单。我使用 DP[i] 来存储:在 i 之前比DP[i]小的数 的个数,当然还要加上 DP[i] 本身的1。如 [2,3,5,1],dp[0]=1, dp[2]=3。
public int lengthOfLIS(int[] nums) {
int maxLength=0;
int[] DP=new int[nums.length];
for(int i=0;i<nums.length;i++){
DP[i]=1;
for(int j=0;j<i;j++){
if(nums[j]<nums[i]){
DP[i]=Math.max(DP[i],DP[j]+1);
}
}
if(DP[i]>maxLength){
maxLength=DP[i];
}
}
return maxLength;
}
这道题有solutions:
https://leetcode.com/problems/longest-increasing-subsequence/solution/
Approach #3 Dynamic Programming [Accepted]
Algorithm
dp[i] 存储以nums[i] 结尾的最长递增子序列的长度。
dp[i]=max(dp[j])+1 , ∀ 0≤j<i
最后, dp[i] 的最大值就是我们需要的结果。
LISlength=max(dp[i]) , ∀ 0≤i<n
Java
public class Solution { public int lengthOfLIS(int[] nums) { if (nums.length == 0) { return 0; } int[] dp = new int[nums.length]; dp[0] = 1; int maxans = 1; for (int i = 1; i < dp.length; i++) { int maxval = 0; for (int j = 0; j < i; j++) { if (nums[i] > nums[j]) { maxval = Math.max(maxval, dp[j]); } } dp[i] = maxval + 1; maxans = Math.max(maxans, dp[i]); } return maxans; } }
Complexity Analysis
-
Time complexity : O(n2). Two loops of n are there.
-
Space complexity : O(n). dp array of size n is used.
Approach #4 Dynamic Programming with Binary Search[Accepted]:
Algorithm
同样也使用DP。从左到右遍历数组,DP数组存储 包含当前遇到元素的递增子序列。当遍历数组时,使用迄今为止遇到的元素来填充DP数组。比如,当前遇到的元素是 the jth index (nums[j]), 我们需要使用二分查找来考虑它在DP数组中的正确位置(say ith index) ,可以用二分查找是因为DP数组存储的是递增子序列。使用 len 来记录DP的长度。 DP不一定结果是最长递增子序列,但是DP的长度会是最长子序列的长度。
比如这个例子:
input: [0, 8, 4, 12, 2]
dp: [0]
dp: [0, 8]
dp: [0, 4]
dp: [0, 4, 12]
dp: [0 , 2, 12] which is not the longest increasing subsequence, but length of dp array results in length of Longest Increasing Subsequence.
更详细的解释见:http://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/
Java
public class Solution { public int lengthOfLIS(int[] nums) { int[] dp = new int[nums.length]; int len = 0; for (int num : nums) { int i = Arrays.binarySearch(dp, 0, len, num); if (i < 0) { i = -(i + 1); } dp[i] = num; if (i == len) { len++; } } return len; } }
注意: Arrays.binarySearch() 返回 search key 的索引。如果它不在array中,返回 (-(insertion point) - 1) 。(The insertion point 指如果它要被插进数组中,应当插入的那个索引,即当前数组中第一个比它大的值的index。如果数组中所有元素都比它小,就是数组的长度)。
Complexity Analysis
-
Time complexity : O(nlog(n)). Binary search takes log(n) time and it is called n times.
-
Space complexity : O(n). dp array of size n is used.