LeetCode刷題Medium篇Longest Increasing Subsequence
阿新 • • 發佈:2019-01-03
題目
Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Input:[10,9,2,5,3,7,101,18]
Output: 4 Explanation: The longest increasing subsequence is[2,3,7,101]
, therefore the length is4
.
Note:
- 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?
十分鐘嘗試
很明顯是個動態規劃問題,設計陣列,儲存當前元素為止增加的序列長度,求出結果後發現怎麼都不對,原來題目沒有要求必需連續,我寫的演算法是求連續增加子序列最大長度,另外最初我用的二維陣列,一直以為需要二維陣列,其實一緯陣列就可以。二維結果也一樣。先貼出這個題目的解法,如下:
class Solution { public int lengthOfLIS(int[] nums) { if(nums.length==0) return 0; if(nums.length==1) return 1; int[][] dp=new int[nums.length][nums.length]; for(int k=0;k<nums.length;k++){ dp[k][0]=1; } int max=1; for(int i=0;i<nums.length;i++){ for(int j=1;j<nums.length;j++){ if(nums[j]>nums[j-1]){ dp[i][j]=dp[i][j-1]+1; } else{ dp[i][j]=1; } max=Math.max(max,dp[i][j]); } } return max; } }
改成一緯陣列,程式碼如下:
package com.puhui.goosecard.manage; /** * 2 * @Author: kerry * 3 * @Date: 2018/12/7 10:18 * 4 */ public class Test { public static int lengthOfLIS(int[] nums) { if (nums.length == 0) { return 0; } if (nums.length == 1) { return 1; } int[] dp = new int[nums.length]; dp[0] = 1; int max = 1; for (int i = 1; i < nums.length; i++) { if (nums[i] > nums[i - 1]) { dp[i] = dp[i - 1] + 1; } else { //修改第一版,如果小於dp[i][j]為1,截止當前元素自增序列為1 dp[i] = 1; } max = Math.max(max, dp[i]); } return max; } public static void main(String[] args) { int[] nums = {10, 9, 2, 5, 3, 7, 101, 18}; System.out.println(lengthOfLIS(nums)); } }
回到這個題目,這是我第一次用dp解決出來問題,為自己喝彩,雖然題目理解有偏差,但是這個題目應該也是dp問題,來!
class Solution {
public int lengthOfLIS(int[] nums) {
if (nums.length == 0) {
return 0;
}
if (nums.length == 1) {
return 1;
}
int[] dp = new int[nums.length];
dp[0] = 1;
int max = 1;
for (int i = 1; i < nums.length; i++) {
int count=0;
//非必須連續,條件修改為截止到當前元素,比自己小的元素個數,注意不是所有前面小的相加,依靠
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
count++;
}
}
dp[i]=count+1;
max = Math.max(max, dp[i]);
}
return max;
}
}
結果不對,debug發現“求當前元素小的元素個數”這個思路不對,這樣不是增加的了。必須是一直增加的。
第一版的思路結果是計算的連續的,第二版的思路不能保證是自增的。怎麼能保證自增並且包括前面所有的元素呢?
最初我們分解,dp陣列元素的含義是:截止當前元素的最長增加序列(注意不是必須連續的),所以在求當前元素i的dp值,其實就是i之前小於i的那些元素的dp值的最大值。修改後程式碼如下:
class Solution {
public int lengthOfLIS(int[] nums) {
if (nums.length == 0) {
return 0;
}
if (nums.length == 1) {
return 1;
}
int[] dp = new int[nums.length];
dp[0] = 1;
int max = 1;
for (int i = 1; i < nums.length; i++) {
int count=0;
//非必須連續,條件修改為截止到當前元素,比自己小的元素個數,注意不是所有前面小的相加,依靠
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
count=Math.max(count,dp[j]);
}
}
dp[i]=count+1;
max = Math.max(max, dp[i]);
}
return max;
}
}