動態規劃--最長遞增子序列

      已知一個序列 {S1, S2,...,Sn} ,取出若干數組成新的序列 {Si1, Si2,..., Sim},其中 i1、i2 ... im 保持遞增,即新序列中各個數仍然保持原數列中的先後順序,稱新序列爲原序列的一個 子序列

      如果在子序列中,當下標 ix > iy 時,Six > Siy,稱子序列爲原序列的一個 遞增子序列

定義一個數組 dp 存儲最長遞增子序列的長度,dp[n] 表示以 Sn 結尾的序列的最長遞增子序列長度。對於一個遞增子序列 {Si1, Si2,...,Sim},如果 im < n 並且 Sim < Sn ,此時 {Si1, Si2,..., Sim, Sn} 爲一個遞增子序列,遞增子序列的長度增加 1。滿足上述條件的遞增子序列中,長度最長的那個遞增子序列就是要找的,在長度最長的遞增子序列上加上 Sn 就構成了以 Sn 爲結尾的最長遞增子序列。因此 dp[n] = max{ dp[i]+1 | Si < Sn && i < n} 。

因爲在求 dp[n] 時可能無法找到一個滿足條件的遞增子序列,此時 {Sn} 就構成了遞增子序列,因此需要對前面的求解方程做修改,令 dp[n] 最小爲 1,即:

                                         ​

 

對於一個長度爲 N 的序列,最長子序列並不一定會以 Sn 爲結尾,因此 dp[N] 不是序列的最長遞增子序列的長度,需要遍歷 dp 數組找出最大值纔是所要的結果,即 max{ dp[i] | 1 <= i <= N} 即爲所求。

Leetcode : 300. Longest Increasing Subsequence

public int lengthOfLIS(int[] nums) {
    int n = nums.length;
    int[] dp = new int[n];
    for(int i = 0; i < n; i++){
        int max = 1;
        for(int j = 0; j < i; j++){
            if(nums[i] > nums[j]) max = Math.max(max, dp[j] + 1);
        }
        dp[i] = max;
    }
    int ret = 0;
    for(int i = 0; i < n; i++){
        ret = Math.max(ret, dp[i]);
    }
    return ret;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章