leetcode 300. Longest Increasing Subsequence

来源:互联网 发布:python学习手册 mobi 编辑:程序博客网 时间:2024/06/05 11:04

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]dp[i] 存储以nums[i结尾的最长递增子序列的长度。

dp[i] = \text{max}(dp[j]) + 1, \forall 0\leq j < idp[i]=max(dp[j])+∀ 0j<i

最后, dp[i]dp[i 的最大值就是我们需要的结果。

LIS_{length}= \text{max}(dp[i]), \forall 0\leq i < nLISlength=max(dp[i]∀ 0i<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(n^2)O(n2). Two loops of nn are there.

  • Space complexity : O(n)O(n)dpdp array of size nn is used.


Approach #4 Dynamic Programming with Binary Search[Accepted]:

Algorithm

同样也使用DP。从左到右遍历数组,DP数组存储 包含当前遇到元素的递增子序列。当遍历数组时,使用迄今为止遇到的元素来填充DP数组。比如,当前遇到的元素是 the j^{th}jth index (nums[j]nums[j]), 我们需要使用二分查找来考虑它在DP数组中的正确位置(say i^{th}ith index) ,可以用二分查找是因为DP数组存储的是递增子序列。使用 lenlen 来记录DP的长度。 DP不一定结果是最长递增子序列,但是DP的长度会是最长子序列的长度。len = len + 1

比如这个例子:

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 dpdp 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))O(nlog(n)). Binary search takes log(n)log(n) time and it is called nn times.

  • Space complexity : O(n)O(n)dpdp array of size nn is used.