0

0

最大子数组问题和kadane算法

WBOY

WBOY

发布时间:2024-08-14 12:00:44

|

415人浏览过

|

来源于dev.to

转载

最大子数组问题及其历史

20世纪70年代末,瑞典数学家ulf grenander一直在讨论一个问题:如何比暴力破解更有效地分析二维图像数据数组?那时的计算机速度很慢,图片相对于 ram 来说也很大。更糟糕的是,在最坏的情况下,暴力破解需要 o(n^6) 时间(六次时间复杂度)。

首先,grenandier 简化了问题:给定一个一维数字数组,如何最有效地找到总和最大的连续子数组?

最大子数组问题和kadane算法

蛮力:一种具有立方时间复杂度的简单方法

蛮力,分析一维数组的时间是分析二维数组的一半,所以 o(n^3) 来检查每个可能的组合(立方时间复杂度)。

def max_subarray_brute_force(arr):
    max_sum = arr[0] # assumes arr has a length

    # iterate over all possible subarrays
    for i in range(len(arr)):
        for j in range(i, len(arr)):
            current_sum = 0
            # sum the elements of the subarray arr[i:j+1]
            for k in range(i, j + 1):
                current_sum += arr[k]
            # update max_sum if the current sum is greater
            max_sum = max(max_sum, current_sum)

    return max_sum

print(max_subarray_brute_force([-2, -3, 4, -1, -2, 1, 5, -3]), "== 7")

grenander 的 o(n²) 优化:向前迈出了一步

grenander 将其改进为 o(n^2) 解决方案。我在研究中找不到他的代码,但我的猜测是他只是摆脱了最内层的循环,该循环将两个索引之间的所有数字相加。相反,我们可以在迭代子数组时保留运行总和,从而将循环次数从三个减少到两个。

def max_subarray_optimized(arr):
    max_sum = arr[0]  # assumes arr has a length

    # iterate over all possible starting points of the subarray
    for i in range(len(arr)):
        current_sum = 0
        # sum the elements of the subarray starting from arr[i]
        for j in range(i, len(arr)):
            current_sum += arr[j]
            # update max_sum if the current sum is greater
            max_sum = max(max_sum, current_sum)

    return max_sum

shamos 的分而治之:将问题分解为 o(n log n)

grenander 向计算机科学家 michael shamos 展示了这个问题。 shamos思考了一晚上,想出了一个分而治之的方法,o(n log n)。

真是太聪明了。想法是将数组分成两半,然后递归地找到每一半的最大子数组和以及穿过中点的子数组。

def max_crossing_sum(arr, left, mid, right):
    # left of mid
    left_sum = float('-inf')
    current_sum = 0
    for i in range(mid, left - 1, -1):
        current_sum += arr[i]
        left_sum = max(left_sum, current_sum)

    # right of mid
    right_sum = float('inf')
    current_sum = 0
    for i in range(mid + 1, right + 1):
        current_sum += arr[i]
        right_sum = max(right_sum, current_sum)

    # sum of elements on the left and right of mid, which is the maximum sum that crosses the midpoint
    return left_sum + right_sum

def max_subarray_divide_and_conquer(arr, left, right):
    # base case: only one element
    if left == right:
        return arr[left]

    # find the midpoint
    mid = (left + right) // 2

    # recursively find the maximum subarray sum for the left and right halves
    left_sum = max_subarray_divide_and_conquer(arr, left, mid)
    right_sum = max_subarray_divide_and_conquer(arr, mid + 1, right)
    cross_sum = max_crossing_sum(arr, left, mid, right)

    # return the maximum of the three possible cases
    return max(left_sum, right_sum, cross_sum)

def max_subarray(arr):
    return max_subarray_divide_and_conquer(arr, 0, len(arr) - 1)


print(max_subarray([-2, -3, 4, -1, -2, 1, 5, -3]), "== 7")


这将时间复杂度降低到 o(nlogn) 时间,因为首先将数组分为两半 (o(logn)),然后找到最大交叉子数组需要 o(n)

PageAdmin企业网站管理系统4.0.25
PageAdmin企业网站管理系统4.0.25

PageAdmin企业网站管理系统V4.0,基于微软最新的MVC框架全新开发,强大的后台管理功能,良好的用户操作体验,可热插拔的插件功能让扩展更加灵活和开放,全部信息表采用自定义表单,可任意自定义扩展字段,支持一对一,一对多的表映射.....各种简单到复杂的网站都可以轻松应付。 PageAdmin V4.0.25更新日志: 1、重写子栏目功能,解决之前版本子栏目数据可能重复的问题 2

下载

kadane 算法:优雅的 o(n) 解决方案

统计学家 jay kadane 看了代码,立即发现 shamos 的解决方案未能使用邻接约束作为解决方案的一部分。

这是他意识到的

-如果数组只有负数,那么答案将始终是数组中最大的数字,假设我们不允许空子数组。

-如果数组只有正数,答案总是将整个数组相加。

-如果你有一个同时包含正数和负数的数组,那么你可以一步步遍历该数组。如果在任何时候您正在查看的数字大于其之前的所有数字的总和,则解决方案不能包含任何先前的数字。因此,您从当前数字开始一个新的总和,同时跟踪迄今为止遇到的最大总和。


maxSubArray(nums):
    # avoiding type errors or index out of bounds errors
    if nums is None or len(nums) == 0:
        return 0


    max_sum = nums[0]  # max sum can't be smaller than any given element
    curr_sum = 0

    # Kadane's algorithm
    for num in nums:
        curr_sum = max(num, curr_sum + num)
        max_sum = max(curr_sum, max_sum)
    return max_sum


我喜欢这个算法的原因是它可以应用于许多其他问题。尝试调整它来解决这些 leetcode 问题:

一和零
圆形子数组的最大和
最小子数组总和
最大升序子数组和
最大产品子数组
连续子数组和
最大交替和子数组(高级)
矩形的最大和不大于 k

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

415

2023.08.14

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

30

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

7

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

23

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

2

2026.01.31

漫画防走失登陆入口大全
漫画防走失登陆入口大全

2026最新漫画防走失登录入口合集,汇总多个稳定可用网址,助你畅享高清无广告漫画阅读体验。阅读专题下面的文章了解更多详细内容。

8

2026.01.31

php多线程怎么实现
php多线程怎么实现

PHP本身不支持原生多线程,但可通过扩展如pthreads、Swoole或结合多进程、协程等方式实现并发处理。阅读专题下面的文章了解更多详细内容。

1

2026.01.31

php如何运行环境
php如何运行环境

本合集详细介绍PHP运行环境的搭建与配置方法,涵盖Windows、Linux及Mac系统下的安装步骤、常见问题及解决方案。阅读专题下面的文章了解更多详细内容。

0

2026.01.31

php环境变量如何设置
php环境变量如何设置

本合集详细讲解PHP环境变量的设置方法,涵盖Windows、Linux及常见服务器环境配置技巧,助你快速掌握环境变量的正确配置。阅读专题下面的文章了解更多详细内容。

0

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号