leetcode-300 最長上升子序列 O(NlogN)解法

1. 題目內容

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

示例:

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

說明:

  • 可能會有多種最長上升子序列的組合,你只需要輸出對應的長度即可。
  • 你算法的時間複雜度應該爲 O(n2) 。

進階: 你能將算法的時間複雜度降低到 O(n log n) 嗎?

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/longest-increasing-subsequence
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

2. 基本思路

來自極客時間的課程,覃超老師講的,現在做筆記記錄如下:

  1. 創建一個數組l用於記錄當前的滿足要求的最長的子序列;
  2. 遍歷整個數組,並調整數組l
  3. 調整規則如下:
    <1> 若當前元素大於數組l中所有元素,則l長度加一,將當前元素添加入l
    <2> 否則,找到l中比當前元素大的元素中的最小值,用當前元素替換,使用二分查找(這也是時間複雜度中logN的來源);
    <3> 遍歷完畢後返回l的長度即可

3. 代碼實現(Python)

class Solution(object):
    def binary_search(self, num, lts):      # 二分查找,找到當前元素的插入位置
        l = len(lts)
        left = 0
        right = l - 1
        while left < right:
            mid = (left + right) // 2
            if lts[mid] < num < lts[mid+1]:
                return mid+1
            elif num > lts[mid]:
                left = mid+1
            else:
                right = mid

    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        lts = [nums[0]]
        for num in nums[1:]:
            if num > lts[-1]:
                lts.append(num)
            elif num < lts[0]:
                lts[0] = num
            elif num in lts:
                continue
            elif num < lts[-1]:
                n_l = self.binary_search(num, lts)
                lts[n_l] = num
        print(lts)
        return len(lts)


def main():
    nums = [10, 9, 2, 5, 3, 7, 101, 18, 20]
    a = Solution()
    res = a.lengthOfLIS(nums)
    # print(res)


if __name__ == '__main__':
    main()

對於main()中給出的數組,遍歷時子序列數組內容依次爲:

[10]
[9]
[2]
[2, 5]
[2, 3]
[2, 3, 7]
[2, 3, 7, 101]
[2, 3, 7, 18]
[2, 3, 7, 18, 20]

4. 小結

本題較爲常規的解法似乎是動態規劃,時間複雜度爲O(N^2),本文的解法似乎屬於奇技淫巧型,但細想之下會覺得這是需要基礎非常牢靠才能想得出的解法,因此記錄一下。
此外,這一次順便複習了二分查找的寫法,發現之前掌握的很不牢靠,自己寫的很痛苦,想用遞歸實現,後來去搜了一個例子,才學會,而且更新 left 或 right 的時候需要實際寫一下看看要不要 mid±1.

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