leetcode 53 Maximum Subarray

本文介绍了求解子数组和的最大值问题的两种方法:动态规划法与分治法。动态规划法通过局部最优值与全局最优值的迭代更新实现O(n)的时间复杂度;分治法则将问题分解为子问题并递归求解,达到O(nlogn)的时间复杂度。

 

53Maximum Subarray    40.10%子数组和的最大值
动态规划法Dynamic Programming:时间复杂度为o(n),试想从头遍历这个数组。对于数组中的其中一个元素,它只有两个选择:
           1. 要么加入之前的数组加和之中(跟别人一组)
           2. 要么自己单立一个数组(自己单开一组)。
          构造一个局部最优值和一个全局最优值

分治法:时间复杂度为o(nlogn),将数组均分为两个部分,那么最大子数组会存在于:
             1. 左侧数组的最大子数组
             2. 右侧数组的最大子数组
             3. 左右数组分界处的最大子数组

 

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Jan 24 22:02:47 2018

@author: vicky
"""


class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
#        #时间超了
#        x=min(nums)
#        for i in range(len(nums)):
#            for j in range(i,len(nums)):
#                    x=max(x,sum(nums[i:j+1]))
#        return x

#法1:动态规划法Dynamic Programming:时间复杂度为o(n)
#试想从头遍历这个数组。对于数组中的其中一个元素,它只有两个选择:
# 1. 要么加入之前的数组加和之中(跟别人一组)
# 2. 要么自己单立一个数组(自己单开一组)
#所以对于这个元素应该如何选择,就看他能对哪个组的贡献大。
#如果跟别人一组,能让总加和变大,还是跟别人一组好了;
#如果自己起个头一组,自己的值比之前加和的值还要大,那么还是自己单开一组好了。
#所以利用一个l数组,记录每一轮的最大值,
#l表示当前这个元素是跟之前数组加和一组还是自己单立一组好,然后维护一个全局最大值即为答案。
        l=0   #局部最大值,变换起点,大于0则起点不变,小于0则起点变为当前值
        g=nums[0]  #全局最大值,变换终点
        for i in range(len(nums)):
            if l>0:#如果当前的局部最大值l是为正的,则加上数组的当前查找值nums[i]
                l=l+nums[i]
            else:#如果l为负,则加上他不如不要,所以直接用当前查找值nums[i]为新的起点
                l=nums[i]
            g=max(g,l)#全局最优=当前的局部最优or还是原来的全局最优
        return g
    
#更简便写法,善用max()对比而不用if判断
        l=0
        g=nums[0]
        for i in range(len(nums)):
            l=max(nums[i],l+nums[i])#用max对比l和0的大小
            g=max(g,l)
        return g
    
#法2:分治法:时间复杂度为o(nlogn)
#将数组均分为两个部分,那么最大子数组会存在于:
# 1. 左侧数组的最大子数组 
# 2. 右侧数组的最大子数组
# 3. 左右数组分界处的最大子数组
class Solution(object):
    def maxSubArrayHelper(self,nums, l, r):
        if l > r:
            return -2147483647
        m = (l+r) / 2

        leftMax = sumNum = 0
        for i in range(m - 1, l - 1, -1):  # 从中间向左遍历
            sumNum += nums[i]
            leftMax = max(leftMax, sumNum)

        rightMax = sumNum = 0
        for i in range(m + 1, r + 1):  # 从中间向右遍历
            sumNum += nums[i]
            rightMax = max(rightMax, sumNum)

        leftAns = self.maxSubArrayHelper(nums, l, m - 1) #递归
        rightAns = self.maxSubArrayHelper(nums, m + 1, r)

        return max(leftMax + nums[m] + rightMax, max(leftAns, rightAns))

    def maxSubArray(self, nums):
        return self.maxSubArrayHelper(nums, 0, len(nums) - 1)


if __name__ == "__main__":
    nums=[1]
    print(Solution().maxSubArray(nums))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值