300. 最长上升子序列

300. 最长上升子序列

题意

给定一个无序的整数数组,找到其中最长上升子序列的长度。

解题思路

  • 动态规划:看到这种题目首先想到的就是dp,受到之前最长回文子串的影响,也以为是要用二维数组来解,然后用(i,j)记录区间的最长值,后来发现完全没有必要。

    假设dp[i]表示0到i中的最长序列长度,如果之前的值比当前值小,则说明之前的值和当前值构成一个递增序列,所以状态转移方程为:

    dp[cur] = max(dp[cur], dp[i] + 1) (if i < cur and nums[cur] > nums[i])

  • 二分查找:维护一个有序序列,如果当前值在这个有序序列中排在最后面,说明当前值加入到有序序列中依然有序,否则则进行替换,时间复杂度为O(nlogn);

实现

class Solution(object):
   def lengthOfLIS(self, nums):
       """
      :type nums: List[int]
      :rtype: int
      """
       if not nums:
           return 0
       
       dp = [1] * len(nums)
       for i in range(len(nums)):
           for j in range(i):
               if nums[j] < nums[i]:
                   dp[i] = max(dp[i], dp[j] + 1)
       return max(dp)
     
def lengthOfLIS(self, nums):
       """
      :type nums: List[int]
      :rtype: int
      """
       if not nums:
           return 0

       dp = []  # 维护一个最长的有序数组
       for i in range(len(nums)):
           low, high = 0, len(dp)

           # 判断nums[i]在数组中是否有序
           while low < high:
               mid = (low + high) // 2
               if nums[i] > dp[mid]:
                   low = mid + 1
               else:
                   high = mid

           # 如果值的位置在最后,插入后依旧保持有序,相反,则替换掉原来位置的值
           if low >= len(dp):
               dp.append(nums[i])
           else:
               dp[low] = nums[i]

       return len(dp)
posted @ 2017-09-06 16:22  banananana  阅读(151)  评论(0编辑  收藏  举报