zoukankan      html  css  js  c++  java
  • python实现连续子数组的最大和

    题目描述

    HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

     方法一:穷举法

    我们很自然地能想到穷举的办法,穷举所有的子数组的之和,找出最大值。

    i, j的for循环表示x[i..j],k的for循环用来计算x[i..j]之和。

    # -*- coding:utf-8 -*-
    class Solution:
        def FindGreatestSumOfSubArray(self, array):
            # write code here
            maxsofar = 0
            for i in range(0,len(array)):
                for j in range(i,len(array)):
                    presum = 0
                    for k in range(i,j):
                        presum += array[k]
                    maxsofar = max(maxsofar, presum)
            return maxsofar
    #bug:不适合最大的<0的情况。
    #例如:[-2,-8,-1,-5,-9]
    # 对应输出应该为:-1
    # 你的输出为:0
    

     有三层循环,穷举法的时间复杂度为O(n3)。

    对穷举法的改进1:

    我们注意到x[i..j]之和 = x[i..j-1]之和 + x[j],因此在j的for循环中,可直接求出sum。

    # -*- coding:utf-8 -*-
    class Solution:
        def FindGreatestSumOfSubArray(self, array):
            # write code here
            maxsofar = 0
            for i in range(0,len(array)):
                presum = 0
                for j in range(i,len(array)):
                    presum += array[j]
                    maxsofar = max(maxsofar, presum)
            return maxsofar
    #bug:不适合最大的<0的情况。
    #例如:[-2,-8,-1,-5,-9]
    # 对应输出应该为:-1
    # 你的输出为:0
    
    改进之后的时间复杂度变为o(n2

    对穷举法的改进2

    在计算fibonacci数时,应该还有印象:用一个累加数组(cumulative array)记录前面n-1次之和,计算当前时只需加上n即可。同样地,我们用累加数组cumarr记录:cumarr[i] = x[0] + . . . +x[i],那么x [i.. j]之和 = cumarr[j] -cumarr[i - 1]

    cumarr[-1] = 0
    for i = [0, n)
        cumarr[i] = cumarr[i-1] + x[i]
        
    maxsofar = 0
    for i = [0, n)
        for j = [i, n)
            sum = cumarr[j] - cumarr[i-1]
            /* sum is sum of x[i..j] */
            maxsofar = max(maxsofar, sum)
    

    时间复杂度为o(n2

    方法二:举例分析数组的规律

    思路:

    最大和连续子数组一定有如下几个特点:

    1. 第一个不为负数
    2. 如果前面数的累加值加上当前数后的值会比当前数小,说明累计值对整体和是有害的;如果前面数的累加值加上当前数后的值比当前数大或者等于,则说明累计值对整体和是有益的。

    步骤:

    1、定义两个变量,一个用来存储之前的累加值,一个用来存储当前的最大和。遍历数组中的每个元素,假设遍历到第i个数时:
      ①如果前面的累加值为负数或者等于0,那对累加值清0重新累加,把当前的第i个数的值赋给累加值。
      ②如果前面的累加值为整数,那么继续累加,即之前的累加值加上当前第i个数的值作为新的累加值。
    2、判断累加值是否大于最大值:如果大于最大值,则最大和更新;否则,继续保留之前的最大和。

    # -*- coding:utf-8 -*-
    class Solution:
        def FindGreatestSumOfSubArray(self, array):
            # write code here
            sum = array[0]
            presum = 0
            for i in array:
                if presum < 0:
                    presum = i
                else:
                    presum += i
                sum = max(presum,sum)
            return sum
    

     分治法,动态规划,未完待


     
  • 相关阅读:
    课堂作业02
    模仿JavaAppArguments.java示例,编写一个程序,此程序从命令行接收多个数字,求和之后输出结果。
    Feign使用Hystrix无效原因及解决方法
    解决Spring Boot 使用RedisTemplate 存储键值出现乱码 xacxedx00x05tx00
    consul怎么在windows下安装
    java运行jar命令提示没有主清单属性
    Maven parent.relativePath
    Maven的pom.xml文件结构之基本配置packaging和多模块聚合结构(微服务)
    redis开启远程访问
    kibana使用
  • 原文地址:https://www.cnblogs.com/tianqizhi/p/9819702.html
Copyright © 2011-2022 走看看