算法导论——最大子数组问题

【算法导论】最大子数组问题的三种解法 【算法导论】最大子数组问题的三种解法 标签(空格分隔):【算法导论】 首先补充两个数学公式: alogbc=clogbaa^{log_bc} = c^{log_ba}alogb​c=clogb​a log(n!)=Θ(nlogn)log(n!) = \Theta(nlogn)log(n!)=Θ(nlogn) 什么是最大子数组问题? 给定一数组A, 寻找A中和最大的非空连续子数组。 例如: ... 阅读详情

方法一:
暴力求解

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
int maxsubset(int *a,int len){
    int summax=INT_MIN;
    int i,j,k;
    for(i=0;i<len;i++)
        for(j=i;j<len;j++){
            int temp=0;
            for(k=i;k<=j;k++)
                temp+=a[k];
            if(temp > summax) summax=temp;
        }
    return summax;
}
int main(){
    int a[]={3,-1,2,5,-3,4,-6,-7,1,8,-3,5,9};
    printf("the maxsubset:%d\n",maxsubset(a,13));
    return 0;
}

方法二:分治求解

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
int cross_middle(int *a,int l,int m,int r){
    int i,
        sum=0,
        l_max=INT_MIN,
        r_max=INT_MIN;
    for(i=m;i>=l;i--){
        sum+=a[i];
        if(sum > l_max) l_max=sum;
    }
    sum=0;
    for(i=m+1;i<=r;i++){//最早i=m,出现BUG
        sum+=a[i];
        if(sum>r_max) r_max=sum;
    }
    return (l_max+r_max);
}
int maxsubset(int *a,int l,int r){
    if(l == r) return a[l];
    //if(l>r) return 0;

    int m=(l+r)/2,
        l_max=INT_MIN,
        r_max=INT_MIN,
        c_max=INT_MIN;
    l_max=maxsubset(a,l,m);
    r_max=maxsubset(a,m+1,r);
    c_max=cross_middle(a,l,m,r);
    if(l_max >= r_max&&l_max >= c_max) return l_max;
    else if(r_max >= l_max&&r_max >= c_max) return r_max;
    else return c_max;
}
int main(){
    int a[]={3,-1,2,5,-3,4,-6,-7,1,8,-3,5,9};

    printf("the maxsubset:%d\n",maxsubset(a,0,12));
    return 0;
}

方法三 线性时间实现:

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
int maxsubset(int *a,int l,int r){
    int i,
        temp=0,
        summax=INT_MIN;
    for(i=l;i<=r;i++){
        temp+=a[i];
        if(temp > summax) summax=temp;
        if(temp < 0) temp=0;
    }
    return summax;
}
int main(){
    int a[]={3,-1,2,5,-3,4,-6,-7,1,8,-3,5,9};

    printf("the maxsubset:%d\n",maxsubset(a,0,12));
    return 0;
}

方法三线性时间实现基于这样的思路:
如果a[1..j]已经得到了其最大子数组,那么a[1..j+1]最大子数组只能是两种情况
(1)a[1..j+1]的最大子数组就是a[1..j];
(2)a[1..j+1]的最大子数组是a[i..j+1],1<=i<=j;
那么,如何求得所谓的(2)中的a[i..j+1]呢?
首先需要承认这样的事实,如果一个数组a[p..r]求和得到负值,那么数组a[p..r+1]的最大子数组肯定不会是a[p..r+1],因为a[p..r]+a[r+1]<a[r+1].
在以上程序中,我们用temp存储所谓的a[p..r],只要a[p..r]的求和是负值,那么从下一个a[r+1]值开始,temp重新从零开始求和,只要temp > summax,就更新summax,这样,我们一次遍历后,就能得到最大的summax,接下来,我们证明该算法是有效的
证明:
对于所有数组元素,这样的元素对数组进行划分,如果加上该元素之前temp>0且temp+a[i]<0,那么该元素a[i]是一个边界,这样,数组会形成好多段,每段结束元素都满足temp>0且temp+a[i]<0.所以我们能得到多个划分块a[p..q],每个划分快的和是负值,划分块有这样的性质,对任意p<=i<q,显然,sum(a[p..i])>=0且sum(a[i..q])<0;
我们要证明

(1)最大子数组一定在划分块之内
证明:
根据划分快性质,容易证明,只要子数组横跨多个划分快,其求和值必定小于某个单独的划 分快中的数组求和。

(2)一定存在首元素以划分块的首元素开始的最大子数组。

证明:
对于某个划分快a[p..q],假设存在a[i..j],其中p<i<=j<q,那么根据划分块性质,a[p..i-1]+a[i..j]>=a[i..j]必定成立,得证。
所以,经历一次遍历,对于每个划分块,从首元素开始求和,得到最大值更新summax,一定能够得到最大子数组的值。

//-------------------------------------------------------------------------
求数组的最大子数组的积怎么求呢?
解决方法是保存最大负值和最大正值,实现如下:

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
int sunsetmax_mul(int *a,int l,int r){
    int i,temp,
        nmax=0,//negtive max
        pmax=0,//positive max
        _max=a[l];
        nmax=(_max<0 ? _max : 0);
        pmax=(_max>0 ? _max : 0);
    for(i=l+1;i<=r;i++){
        if(a[i] < 0){
            temp=pmax;
            pmax=nmax==0 ?  0 : nmax*a[i];
            nmax=temp==0 ?a[i]: temp*a[i];
        }
        else if(a[i] > 0){
            pmax=pmax==0 ? a[i]: pmax*a[i];
            nmax=nmax==0 ?   0 : nmax*a[i];
        }
        else {
            pmax=nmax=0;
        }
        if(pmax > _max) _max=pmax;
    }
    return _max;
}
int main(){
    int a[]={-2,2,2,-5,2/*,5,-3,4,-6,-7,1,8,-3,5,9*/};
    printf("max mul subset result is %d\n",sunsetmax_mul(a,0,4));
}

其他思想:
另一种思路(包括最大子数组的积)

求不相交两个子数组的最大和

《算法导论》第4章 分治策略(递归,最大子数组问题,矩阵的Strassen乘法) (最近在自己学习《算法导论》一本书,之前本来喜欢手写笔记,但是随即发现自己总是把笔记弄丢,所以打算做一个电子版的笔记) (另外书中用的都是伪代码,笔记中如果需要尝试的地方都是python代码) 分治策略:递归地求解问题,往往可以分为三个步骤: 分解(Divide)将问题划分为一些子问题,子问题的形式与原问题一样,只是规模更小。 解决(Conquer)递归地求解出子问题,如果子问题的规模足够小就直接求解 合并(Combie)将子问题的解组合成原问题的解。 ... 阅读详情

相关推荐

利用HFSS仿真优化圆极化微带天线的耦合馈电设计

本文深入探讨了利用HFSS仿真软件优化圆极化微带天线性能的关键方法。通过对比传统直接馈电与耦合馈电方式,详细阐述了耦合馈电在提升阻抗匹配、改善轴比带宽及增强设计鲁棒性方面的显著优势。文章结合FR4板材的实战案例,逐步演示了在HFSS中建立模型、进行参数扫描与圆极化性能优化的完整流程,为设计高性能、高纯度的圆极化天线提供了实用指南。

weixin_29233333的博客 547

连续子数组的最大和问题(五种解法)

昨天软考(2021年5月29日)试卷上出现了的算法题,问:连续子数组最大和的分治解法的时间复杂度,考完正好总结一下这道算法题。 求连续子数组的最大和 题目描述: 输入一个整型数组,数组里有正数也有负数。 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。 比如上面这个数组的子数组的最大和为187,从下标3到下标7的位置。(本文中数组下标从1开始) 思路 比较常规的思路是暴力(O(n3))、前缀和数组(O(n2))两种,但是时间复杂度比较高,这题也可以用分治的策略做,时间复杂度O(nl.

weiambt的博客 3万+

2025年MathorCup数学应用挑战赛【B题完整论文】附参考代码(免费分享)

摘。

RS_handy的博客 2694

算法导论----最大子数组问题(分治算法)

摘自算法导论,加上自己的一点理解

m0_74142238的博客 2353

Centos7搭建OpenStack+创建iaas云主机

主要说明在控制节点和计算节点上,通过脚本的形式,安装OpenStack的iaas安装步骤和创建可运行的云主机。提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。

weixin_48218106的博客 1万+

ESP32Servo库驱动SG90舵机:从入门到精准控制

本文详细介绍了如何使用ESP32Servo库驱动SG90舵机,从硬件连接到软件环境搭建,再到编写示例程序实现精准控制。内容涵盖库安装、基础驱动代码解析、舵机校准方法以及平滑运动控制,帮助开发者快速掌握ESP32控制舵机的核心技能,并提供了电源管理、信号抗干扰等实用避坑指南。

ik678901的博客 897

最大子数组的和问题--线性算法

最大子数组的和问题–线性算法 计算给定数组的最大子数组的和有很多种算法,最常见的是使用分治的策略,然而此问题用分治却增加了时间复杂度和代码复杂度。有更简单的算法,本文就将介绍一个线性时间的迭代算法。这应该是最高效的解决方法了。

zj0395的博客 6202

从混乱到清晰:用QJsonObject重构你的Qt网络API数据解析层(避坑指南)

本文详细介绍了如何使用QJsonObject重构Qt网络API数据解析层,避免常见的JSON解析陷阱。通过安全解析模式、数据绑定和性能优化技巧,帮助开发者构建高效、健壮的解析逻辑,提升代码可维护性和可读性。特别适用于处理复杂嵌套的JSON响应数据场景。

weixin_29011667的博客 230

最大和子数组/最大和子序列

  最大和子数组是数组中和最大的子数组,又名最大和子序列。子数组是数组中连续的n个元素,比如a2,a3,a4就是一个长度为3的子数组。顾名思义求最大和子数组就是要求取和最大的子数组。      n个元素的数组包含n个长度为1的子数组:{a0},{a1},…{an-1};   n个元素的数组包含n-1个长度为2的子数组:{a0,a1},{a1,a2},{an-2,an-1};   ...

avoqgc0645的博客 414

告别环境依赖!用PyInstaller把PaddleOCR项目打包成独立EXE(附完整spec文件配置)

本文详细介绍了如何使用PyInstaller将PaddleOCR项目打包成独立EXE文件,彻底解决Python环境依赖问题。通过完整的spec文件配置和实战技巧,开发者可以轻松创建开箱即用的OCR工具,特别适合需要交付给非技术用户的场景。文章涵盖环境配置、模型打包、性能优化等关键环节,并提供了解决常见问题的方案。

weixin_33712987的博客 573

科研绘图系列:R语言绘制差异蝴蝶图(Butterfly Chart)

科研绘图系列:R语言蝴蝶图(Butterfly Chart)

专注生信领域 1390

LeetCode 一题多解 | 53. 最大子数组和:五种解法完全手册

作者:nettee 公众号:面向大象编程一、原题描述 LeetCode 53. Maximum Subarray 最大子序和二、全部解法 本文将介绍「最大子数组和」...

nettee的专栏 1509

华为校招&实习&留学生机试真题目录+算法分类+在线OJ+通过率+视频讲解

全网最新最全华为校招&实习&留学生机试真题题库

m0_73659489的博客 6868

【算法导论】最大子数组问题

#include #define LENGTH 16 //定义一个结构,记录了左右下表和总和,原因在于用于数据返还 typedef struct { int low; int high; int sum; }parm; parm findMaxCrossingSubarray(int number[],int low,int mid,int high)

Code for Yun 2553

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

算法导论之最大子数组问题 C语言实现

算法导论之最大子数组问题 C语言实现

Pandamentle的博客 763

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

算法导论之最大子数组问题

例如我们在求解下面的最大子数组时 13 -3 -25 20 -3 -16 -23 18 20 -7 12 -5 -22 15 -4 7     最简单的做法就是暴力求解,但是时间复杂度为O(n^2); // // main.cpp // 算法导论 // // Created by SJCH...

SJCHEN1221的博客 478

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Java动态规划解决最大子数组问题,线性时间复杂度。(算法导论4.1)

package 最大子数组; import java.util.Arrays; /* * 动态规划方法解决最大子数组问题 * */ public class Solution { public static void main(String[] args) { // TODO 自动生成的方法存根 int[] arr = new int[] {13,-3,-25,20,-3,-...

qq_34553282的博客 786

算法导论--最大子数组问题

最大子数组问题: 问题描述:   假定你获得了投资挥发性化学公司的机会。与其生产的化学制品一样,这家公司的股票价格也是不稳定的。你被准许可以在某个时刻买进一股该公司的股票,并在之后某个日期将其卖出,买进卖出都是在当天交易结束后进行。为了补偿这一限制,你可以了解股票将来的价格。你的目标是最大化收益。 虽然最高价卖出,最近价买进是收益最大化,但是在一段给定时期内,可能无法做到在最低价格时买进股票...

jiangbinbin的博客 527

算法导论——分治策略——最大子数组问题

最大子数组:一个数组A的和最大的非空连续子数组。 注意:只有当数组中包含负数时,最大子数组问题才有意义。 暴力求解法:(对每个子数组求和,选出和最大的子数组) 分治策略求解方法: 将数组分成规模尽可能相等的子数组,即找到中间位置,然后考虑左子数组和右子数组,最大子数组位置必然有以下三种情况: 完全位于左子数组中 2) 跨过了中点 3) 完全位于右子数组中 分别求出三种情况下的最大子数组,再选出三...

weixin_45115866的博客 620

算法导论之求解最大子数组问题python代码实现

算法导论之最大子数组问题 使用分治策略求解 基于python的源代码如下: #求出跨越中点的最大子数组 def FIND_MAX_CROSSING_SUBARRARY(list,low,mid,high): left_max = -float("inf") right_max = -float("inf") left_sum = 0 right_sum = 0 left_index = ...

weixin_45184423的博客 356

最大子数组问题--算法导论

if sum > left-sum //找出和最大的组合,赋值给left-sum,并且将下标赋给max-left。求左边和右边的最大子数组是在递归中可以由求中间的最大子数组求出,看到后面的分解过程就会明白了,我们主要解决求中间的最大子数组问题。FIND-MAX-CROSSING-SUBARRAY(A, low ,mid , high) //输入数组和左中右的下标。//找到了左边和右边的最大组合,返回左边下标和右边小标以及找出的跨越中间的最大数组的值。//同左边的操作相同。

Hennan_Dianzi_C的博客 1788

算法导论 — 4.1 最大子数组问题

笔记 本节给出了分治法的一个例子。给定一个数组A[1..n]A[1..n]A[1..n],找出一个元素和为最大的连续子数组A[i..j]A[i..j]A[i..j],其中1≤i≤j≤n1 ≤ i ≤ j ≤ n1≤i≤j≤n,称这样的子数组为最大子数组。例如,下图所示数组中,第888个元素到第111111个元素之间的子数组为最大子数组。      求解最大子数组问题,最简单的方法是暴力检查所有的子...

yangtzhou的专栏 2058

算法导论————最大子数组问题(C,Java,python)

我们来思考如何用分治技术来求解最大子数组问题。假定我们要寻找子数组A[ lorw. . high]的最大子数组。使用分治技术意味着我们要将子数组划分为两个规模尽量相等的子数组。也就是说,找到子数组的中央位置,比如mid,然后考虑求解两个子数组A[low. . mid]和A[mid+1.. high]。

qq_52659550的博客 1211

Java实现《算法导论》最大子数组问题

算法导论第四章分治策略38页最大子数组问题Java实现,算法见书中 public class Main { static class Result { public int left; public int right; public int maxSum; public Result(int left, int right, int maxSum) { thi

Silence_1992w的博客 557

【Coding算法导论】第4章:最大子数组问题

Coding算法导论 本系列文章主要针对算法导论一书上的算法,将书中的伪代码用C++实现 代码未经过大量数据测试,如有问题,希望能在回复中指出! (一)问题描述给定一个数组,求数组中连续的子数组的和,找出和的最大值。如 数组A:-1,-4,4,3,2,-3 应该返回最大值9。(二)问题求解本题想到了两个思路:暴力求解法和分治法。前者就不多说了,本文主要讨论分治法。 分治法的大致思路:

ZeeCoder 809
上一篇: 用 Javascript 实现一个简易 BrainF--k 解释器
下一篇: 通过Node.js Stream API 实现逐行读取的实例
叡
叡
博客等级 码龄17年 1粉丝 75原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值