算法刷題(LeetCode:300、最長遞增子序列)

1、題目描述

  給你一個整數數組 nums ,找到其中最長嚴格遞增子序列的長度。算法

  子序列是由數組派生而來的序列,刪除(或不刪除)數組中的元素而不改變其他元素的順序。例如,[3,6,2,7] 是數組 [0,3,1,6,2,2,7] 的子序列。數組

  來源:力扣(LeetCode)
  連接:https://leetcode-cn.com/problems/longest-increasing-subsequencespa

  題目分析

    如他的題目所描述,須要求出【最長遞增子序列】的【長度】。code

    幾個關鍵詞:最長、嚴格遞增、長度。blog

    此處的嚴格遞增指:1,2,7,7的最長遞增子序列長度爲3,由於7和7相等,沒有遞增。leetcode

    舉幾個例子:如{0,3,1,6,2,2,7}它的遞增子序列有:{0,3,6,7} ,{0,1,6,7}, {0,1,2,7}以及一些更短的遞增子序列,而咱們的目標就是求出這些子序列中長度的最大值。get

2、用到的算法思想

  我解這道題用到的有:【動態規劃】(Dynamic Programming 簡稱DP)。io

  解題方式並不惟一,不要侷限於一種方法。class

3、思路

  動態規劃解題四部曲(非準確):找出原問題--->將原問題分解爲規模更小的子問題--->當規模小到必定程度時,答案出現或者很容易求出--->將小的問題合併成原來的問題。
循環

  一樣以數組 {0,3,1,6,2,2,7}爲例:

    咱們能夠很容易的有一種思路,前6個數的最長遞增子序列,前5個數.........

    驗證這種思路是否可行:

      {0,3,1,6,2,2,7} 的最長子序列長度爲4,此時7在最長子序列當中。

    在去掉7之後數組變爲

      {0,3,1,6,2,2} 最長子序列爲3。說明7在最長子序列中,除去也不影響子問題的解。

    再將最後的2一處數組,變爲:

      {0,3,1,6,2} 最長子序列依舊爲3,說明除去的2不在最長子序列中,除去依舊不影響子問題的解。

    ......省略.....

    因而可知,不管被移除數組的那一位是否在最長子序列中,都不影響子問題的解。所以,這個問題具備【最優子結構性質】。

    因此,咱們已經無限接近答案了:

      創建一個dp數組,長度爲【數組長度+1】。

      初始化:dp[0] = 0; dp[i] = 1; (i = 1,2,3...n);

      接着爲表中填入數據,從數組arr第1位開始:填入1;

                    第2位:arr[1]與arr[0]比較,看arr[1]是否>arr[0](便是否遞增),若是遞增,則判斷dp[i+1]和dp[i] + 1二者誰大。

                    第3位:同2,可是須要循環,直到數組下標爲0的位置.......

      {0,3,1,6,2,2,7} 填入的最終dp數組應該爲: {0, 1, 2, 2, 3, 3, 3, 4}。

    須要注意的是:最大值不必定在dp數字最後一位,如:{0,3,1,6,2,2,7,0,0,0} 它最終的dp數組爲:{0, 1, 2, 2, 3, 3, 3, 4, 1,1, 1}, 因此須要循環一次dp數組找出最大值。

4、代碼實現(Java)

class Solution { public int lengthOfLIS(int[] nums) { int[] dp = new int[nums.length+1]; dp[0] = 0; for(int i = 0; i < nums.length; i++){ dp[i+1] = 1; for(int j = i; j >= 0; j--){ if(nums[i] > nums[j]){ dp[i+1] = getMax(dp[j+1]+1, dp[i+1]); } } } int max = 0; for(int i = 0; i <= nums.length; i++){ if(dp[i] > max) max = dp[i]; } return max; } public int getMax(int m, int n){ return m > n ? m : n; } }

5、完成時間

    2021-01-28  15:48:57

    最近幾天在研究動態規劃,刷了七八道題,漸漸地有了一些感受,但動態規劃也分好多種類,好比區間dp,揹包dp,樹形dp等等,須要多加努力。

相關文章
相關標籤/搜索