zoukankan      html  css  js  c++  java
  • 数据结构与算法之【最大子列和问题】

    题目

    【剑指offer】42.连续子数组的最大和

    输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

    示例1

    输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
    输出: 6
    解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

    思路1:暴力破解法,将所有的子列和都列举出来。

    class Solution:
        def maxSubArray(self, nums):  # 暴力求解
            '''
            :param nums: list
            :return: 最大子序列和
            '''
            assert isinstance(nums, list), "nums不是一个list"
    
            l = len(listA)
            MaxSum = 0
            for i in range(l):  # 子序列左段
                TheSum = 0
                for j in range(i, l):  # 子序列右端
                    TheSum += nums[j]
                    if TheSum > MaxSum:
                        MaxSum = TheSum
            return MaxSum
    

    思路2:分而治之。“分”就是将大问题转化为小问题,“治”就是统一起来。算法思路:

    • 情况1:子列和最大值出现在子序列的左段;
    • 情况2: 子列和最大值出现在子序列的右端;
    • 情况3:子列和最大值出现在横跨两端的子列中;
    def maxSubArray2(self, nums, left=0, right=0):  # 分而治之
        '''
        :param nums: list
        :param left: 求最大子列的起始下标
        :param right: 终止下标
        :return: 最大子序列和
        '''
    
        assert isinstance(nums, list), "nums不是一个list"
        assert left <= right, "输入错误,left>right"
    
        s = 0
        midSum = 0
        leftSum = 0
        rightSum = 0
        if left == right:
            s = nums[left]
        else:
            center = (left + right) // 2
            # print("center",center)
            leftSum = self.maxSubArray2(nums, left, center)  # 情况1 最大字段和全部取左边元素
            rightSum = self.maxSubArray2(nums, center + 1, right)  # 情况2 最大字段和全部取右边元素
            s1 = 0;
            lefts = 0  # 求出s1, 从中间到左边的最大和
            for i in range(center, left - 1, -1):
                lefts += nums[i]
                if s1 < lefts:
                    s1 = lefts
            # print("s1:", s1)
            s2 = 0
            rights = 0  # 求出s2, 从中间到右边的最大和
            for i in range(center + 1, right, 1):
                rights += nums[i]
                if s2 < rights:
                    s2 = rights
            # print("s2:", s2)
            midSum = s1 + s2  # 横跨中间的最大子段和
            s = max([midSum, leftSum, rightSum])
    

    思路3:在线处理。优势在于对于任意的输入的子序列,都可以直接输出当前的最大子列和;重点在于当前的子列和能不能对后续的输入有作用,如果为最大子列和为负数则归零,如果加入新的值后当前子列和更大则更新最大子列和的值。

    class Solution:
        def maxSubArray(self, nums: List[int]) -> int:
            '''
            :param nums: list
            :return: 最大子序列和
            '''
            l = len(nums)
            maxSum = nums[0]
            ThisSum = 0
            for i in range(l):
                ThisSum += nums[i]
                if ThisSum > maxSum: # 如果当前子列和更大,则更新masSum
                    maxSum = ThisSum
                if ThisSum < 0: # 如果当前子列和<0,则必然不包括再最大子列和中
                    ThisSum = 0
            return maxSum
    

    提高:除了输出最大子列和以外,还要输出该最大子列的起始值和终了值。如果最大子序列不是唯一的,则输出索引i和j最小的子序列(如示例所示)。 如果所有K个数字均为负,则其最大和定义为0,并且应该输出整个序列的第一个和最后一个数字。

    def maxSubarray3(self, nums):  # 在线处理
        '''
        :param nums: list
        :return: 最大子序列和
        '''
        l = len(nums)
        maxSum = -1
        ThisSum = 0
        left_index, right_index, temp_index = 0, l - 1, 0  # 初始化很重要,对于需要返回下标的时候
        for i in range(l):
            ThisSum += nums[i]
            if ThisSum < 0:
                ThisSum = 0
                temp_index = i + 1
            elif ThisSum > maxSum:
                maxSum = ThisSum
                left_index = temp_index
                right_index = i
        if maxSum < 0:  maxSum = 0
        return maxSum, left_index, right_index
    
  • 相关阅读:
    U盘安装WIN10专业版
    jquery template模版引擎
    MySQL大数据量快速分页实现(转载)
    MySQL for Windows 解压缩版安装 和 多实例安装
    macbook 重装win7
    MySQL for Visual Studio Version
    VS2010中没有ado.net entity data model实体数据模型这一选项-解决办法
    修改server 2008远程桌面端口
    懒加载
    html-css 常用
  • 原文地址:https://www.cnblogs.com/hnxbp/p/13777230.html
Copyright © 2011-2022 走看看