博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DP专题1 - leetcode53. Maximum Subarray/300. Longest Increasing Subsequence - 经典
阅读量:2217 次
发布时间:2019-05-07

本文共 3641 字,大约阅读时间需要 12 分钟。

题目描述

最大连续子序列和。(至少包含一个数组)

例子

Input: [-2,1,-3,4,-1,2,1,-5,4],

Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

思想

法1 - DP。dp[i]表示以i位置结尾的最大值,dp[i] = max(dp[i-1] + nums[i], nums[i]);
法2 - 贪心。如果之前的和小于0,则从当前数字开始。即如果summ<0,则将summ置0;否则继续summ + num。
法3 - 分治法
考虑区间[l, r]内的答案如何计算?
令 mid = (l + r) / 2,则该区间的答案是三部分取最大值,分别是:
(a) 区间 [l, mid] 内的答案(递归)。
(b) 区间 [mid + 1, r] 内的答案(递归)。
(c) 跨越 mid和mid+1 的连续子序列。
其中,(c) 部分只需要从 mid 开始向 l 找连续的最大值,以及从 mid+1 开始向 r 找最大值即可,在线性时间内可以完成。
递归终止条件显然是 l==r ,此时直接返回 nums[l]。

每层时间复杂度是 O(n),总共有 O(logn) 层,故总时间复杂度是 O(nlogn)。

解法1

可以优化空间复杂度,优化后类似法2

class Solution(object):    def maxSubArray(self, nums):        """        :type nums: List[int]        :rtype: int        """        res = nums[0]        dp = [0] * len(nums)    # dp[i]表示以i位置结尾的最大值        dp[0] = nums[0]        for i in range(1, len(nums)):            dp[i] = max(dp[i-1] + nums[i], nums[i])            res = max(res, dp[i])        return res

解法2

class Solution(object):    def maxSubArray(self, nums):        """        :type nums: List[int]        :rtype: int        """        res = summ = nums[0]        for num in nums[1:]:            if summ < 0:                summ = 0            summ += num            res = max(res, summ)        return res

解法3

class Solution(object):    def maxSubArray(self, nums):        """        :type nums: List[int]        :rtype: int        """        return self.helper(0, len(nums)-1, nums)        def helper(self, left, right, nums):        if left == right:            return nums[left]                mid = (left + right) >> 1        # The maxSum including mid and mid+1        lmax = nums[mid]        rmax = nums[mid+1]        lsum = rsum = 0        for i in range(mid, left-1, -1):            lsum += nums[i]**加粗样式**            lmax = max(lsum, lmax)        for i in range(mid+1, right+1):            rsum += nums[i]            rmax = max(rsum, rmax)                    return max(max(self.helper(left, mid, nums), self.helper(mid+1, right, nums)), lmax+rmax)

题目描述

给定无序整数数组,输出最长递增子序列长度。(不连续)

例子

Input: [10,9,2,5,3,7,101,18]

Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.

思想

看到最大,最长 → 想到DP。
法1 - dp[i]表示以nums[i]结尾的最长递增子序列的长度;
初始状态:dp = [1] * len(nums);
状态方程:dp[i] = max(dp[i], dp[j] + 1) if nums[j] < nums[i] 对于j=0,1…i-1;
时间复杂度O(n^2)。
法2 - 优化,时间复杂度(nlogn)

对于一个上升子序列,显然当前最后一个元素越小,越有利于添加新的元素,这样LIS长度自然更长。

维护一arr数组,数组元素表示长度为i+1的LIS结尾元素的最小值(保证每一位都是最小值), 此时arr数组的长度就是LIS的长度

对于每一个num,如果≥arr[-1], 直接插入尾部;否则找到arr第一个大于num的位置, 替换

解法1

class Solution(object):    def lengthOfLIS(self, nums):        """        :type nums: List[int]        :rtype: int        """        if not nums:            return 0                dp = [1] * len(nums)    # dp[i]表示以i结尾的最长递增子序列的长度        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)

解法2

存储长为i+1的LIS结尾元素的最小值

class Solution(object):    def lengthOfLIS(self, nums):        """        :type nums: List[int]        :rtype: int        """        arr = []        for num in nums:            if not arr or num > arr[-1]:                arr.append(num)            else:                pos = self.getFirstLarger(arr, num)                arr[pos] = num        return len(arr)                    def getFirstLarger(self, arr, num):        l = 0        r = len(arr) - 1        while l <= r:            mid = (l + r) >> 1            if arr[mid] < num:                l = mid + 1            else:                if mid > 0 and arr[mid-1] > num:                    r = mid - 1                else:                    return mid

Ref

转载地址:http://tzkfb.baihongyu.com/

你可能感兴趣的文章
PHPUnit安装及使用
查看>>
PHP项目用xhprof性能分析(安装及应用实例)
查看>>
composer安装YII
查看>>
Sublime text3快捷键演示
查看>>
sublime text3 快捷键修改
查看>>
关于PHP几点建议
查看>>
硬盘的接口、协议
查看>>
VLAN与子网划分区别
查看>>
Cisco Packet Tracer教程
查看>>
02. 交换机的基本配置和管理
查看>>
03. 交换机的Telnet远程登陆配置
查看>>
微信小程序-调用-腾讯视频-解决方案
查看>>
phpStudy安装yaf扩展
查看>>
密码 加密 加盐 常用操作记录
查看>>
TP 分页后,调用指定页。
查看>>
Oracle数据库中的(+)连接
查看>>
java-oracle中几十个实用的PL/SQL
查看>>
PLSQL常用方法汇总
查看>>
几个基本的 Sql Plus 命令 和 例子
查看>>
PLSQL单行函数和组函数详解
查看>>