LeetCode 刷題筆記 - 300. 最長上升子序列

難度:

中等swift

描述:

給定一個無序的整數數組,找到其中最長上升子序列的長度。數組

示例:

輸入: [10,9,2,5,3,7,101,18]
輸出: 4 
解釋: 最長的上升子序列是 [2,3,7,101],它的長度是 4。
複製代碼

來源:力扣(LeetCode) 連接:leetcode-cn.com/problems/lo… 著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。bash


語言:

swift網絡

解析:

這也是動態規劃比較基礎的一道題,咱們依舊按照基本解題思路來分析。 要求長度爲 n 的序列的最長上升子序列,首先分解爲子問題:oop

1. 求該序列長度爲 0 的序列的最長上升子序列
2. 求該序列長度爲 1 的序列的最長上升子序列
3. 求該序列長度爲 2 的序列的最長上升子序列
4. 求該序列長度爲 3 的序列的最長上升子序列
5. ...
6. 求該序列長度爲 n 的序列的最長上升子序列
複製代碼

而後設置狀態方程,咱們設d(n)爲該序列長度爲n的時候的最長子序列長度,L[n]爲序列L的第n位元素。ui

先來看第一個問題:
1. 求該序列長度爲 0 的序列的最長上升子序列,顯而易見序列長度爲 0 的時候,最長子序列長度也爲 0 ,因此d(0) = 0
第二個問題:
2. 求該序列長度爲 1 的序列的最長上升子序列的答案爲1,因此d(1) = 1
3. 求該序列長度爲 2 的序列的最長上升子序列的狀況就有所不一樣了,咱們須要比較L[2]L[1]的大小,若是L[2] > L[1],則有d(2) = 2;若是L[2] < L[1],則有d(2) = 1
4. 求該序列長度爲 3 的序列的最長上升子序列的狀況會更加複雜,因爲L[1]L[2]的最長子序列是已知的,咱們僅須要把L[3]分別同L[1]L[2]比較,找到比L[3]小的。例如示例中,d(1) = 1, d(2) = 1, d(3) = 1
5. 求該序列長度爲 4 的序列的最長上升子序列,同上一個子問題同樣,咱們發現L[3] < L[4],因此d(4) = 2,抽象爲d(4) = d(3) + 1 = 1 + 1 = 2
這個時候咱們同時須要考慮,若是第x位元素L[x],在[1, x)區間內有yz兩個元素小於L[x],即L[y] < L[x]L[z] < L[x],那麼咱們須要找到d(y)d(z)中比較大的,因此能夠抽象出方程:d(x) = max{d(y), d(z)} + 1
因此在求解:
6. 求該序列長度爲 n 的序列的最長上升子序列的時候,咱們能夠抽象出狀態轉移方程:
d(i) = max{1, d(j) + 1}(j < i, L[j] < L[i])
咱們須要在遍歷每一個元素的時候,去尋找前面元素中的最長上升子序列。spa

自認爲表達的的還不是太好。。。能夠討論一下,我還會改進。code

代碼以下:leetcode

class Solution {
    func lengthOfLIS(_ nums: [Int]) -> Int {
        if nums.count == 0 {
            return 0
        }
        var dict = [Int : Int]()
        var maxLength = 1
        dict[0] = 1
        for index in 0...nums.count - 1 {
            var length = 0
            if index - 1 < 0 {
                continue
            }
            for loopIndex in 0...index - 1 {
                if nums[loopIndex] < nums[index] && (dict[loopIndex] != nil) {
                    length = max(length, dict[loopIndex]!)
                }
            }
            dict[index] = length + 1
            maxLength = max(maxLength, dict[index]!)
        }
        return maxLength
    }
}
複製代碼

總結

動態規劃頗有趣,要經過多練習才能熟悉。get

相關文章
相關標籤/搜索