求解最大子段和问题

news2024/12/24 9:59:10

求解最大子段和问题。

对于给定序列a1,a2,a3……an,寻找它的某个连续子段,使得其和最大。如( -2,11,-4,13,-5,-2 )最大子段是{ 11,-4,13 }其和为20。

要求:分别用教材所给的三种方法求解(简单方法、分治法、动态规划),通过实例比较结果和时间效率。

提交内容:算法的思想、程序源代码及其说明、实例运行结果及分

简单方法求解:

以a[0]开始: {a[0]}, {a[0],a[1]},{a[0],a[1],a[2]}……{a[0],a[1],……a[n]}共n个

以a[1]开始: {a[1]}, {a[1],a[2]},{a[1],a[2],a[3]}……{a[1],a[2],……a[n]}共n-1个

……

以a[n]开始:{a[n]}共1个

暴力破解方法简单直观,通过两层嵌套循环遍历所有可能的子段,计算它们的和,并保留最大和。这种方法的时间复杂度为O(n^2),适用于小规模数据集。

分治方法:

将序列a[1:n]分成长度相等的两段a[1:n/2]和a[n/2+1:n],分别求出这两段的最大字段和,则a[1:n]的最大子段和有三中情形:

a[1:n]的最大子段和与a[1:n/2]的最大子段和相同;

a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同;

a[1:n]的最大字段和为∑ak,且1<=i<=n/2,n/2+1<=j<=n。

可用递归方法求得情形1、2。对于情形3,可以看出a[n/2]与a[n/2+1]在最优子序列中。因此可以在a[1:n/2]中计算出

,并在a[n/2+1:n]中计算出 。则s1+s2即为出现情形3时的最优值。

        

        分治法采用递归的方式将问题划分成更小的子问题,分别求解子问题的最大子段和,然后合并得到整体的最大子段和。这种方法的时间复杂度为O(n log n),适用于中等规模的数据集。它的优势在于对于更大规模的问题,其效率相对较高。

动态规化:

D[i]表示从i开始的最大字段和。(但我们不是从前往后找字段结束位置)

根据递推公式,我们可知要想求得D[i],就必须知道D[i+1],所以我们从前往后计算。

如下图:以i=12开始的子段和D[12]=X[12]=-1,该子段结束位置Rec[12]=i=12;

当i=11时,D[11+1]<0,所以D[11]=X[11]=7,Rec[i]=i=11;

当i=10时,D[10+1]>0,所以D[10]=X[10]+D[11]=3+7,Rec=i+1=11;


一直到i,我们就找完了所有子段和,接着在子段和中找最大的。

        动态规划采用自底向上的方式,通过迭代计算子问题的最优解,并将结果保存起来,避免了重复计算。这种方法的时间复杂度为O(n),适用于大规模数据集。它的优势在于具有更好的时间效率,但相对于分治法,实现稍显复杂。

实验分析

暴力破解

源码:

//暴力破解

int sum1(int arr[],int len) {

    int sum=0;

    for (int i = 0; i < len; i++) {

         int this_sum = 0;

         for (int j = i; j < len; j++) {

             this_sum += arr[j];

             if (this_sum > sum) {

                  sum = this_sum;

             }

         }

    }

    return sum;

}

分治法:

//分治法

int maxSubSum(int a[], int left, int right) {



    int sum = 0;

    if (left == right) {

         sum = a[left] > 0 ? a[left] : 0;

    }

    else {



         int center = (left + right) / 2;

         int leftSum = maxSubSum(a, left, center);

         int rightSum = maxSubSum(a, center + 1, right);



         int s1 = 0;

         int lefts = 0;

         for (int i = center; i >= left; i--) {



             lefts += a[i];

             if (lefts > s1) s1 = lefts;

         }



         int s2 = 0;

         int rights = 0;

         for (int i = center + 1; i < right; i++) {



             rights += a[i];

             if (rights > s2)  s2 = rights;

         }

         sum = s1 + s2;

         if (sum < leftSum) sum = leftSum;

         if (sum < rightSum) sum = rightSum;

    }

    return sum;

}



int maxSum(int a[], int n) {

    return maxSubSum(a, 0, n - 1);

}

动态规划:

//动态规划

int sum2(int arr[],int len)

{

    int sum=0;

    int b=0;

    int left=0;

    int right=0;

    for (int i = 0; i < len; i++) {

         if (b > 0) {

             b += arr[i];

             right = i;

         }

         else {

             b = arr[i];



         }



         if (sum < b) {

             sum = b;



         }

    }

   

    return sum;



}



实验分析:

测试了2000个数据,除了暴力破解比较慢用了8ms,其他的都不足1ms。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1317815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis】AOF 基础

因为 Redis AOF 的实现有些绕, 就分成 2 篇进行分析, 本篇主要是介绍一下 AOF 的一些特性和依赖的其他函数的逻辑,为下一篇 (Redis AOF 源码) 源码分析做一些铺垫。 AOF 全称: Append Only File, 是 Redis 提供了一种数据保存模式, Redis 默认不开启。 AOF 采用日志的形式来记…

指针必刷题(C语言指针就该这么学)【数据结构基础】【C语言指针必刷题】

前言&#xff1a;必备知识回忆 1.数组名的意义 i.sizeof(数组名&#xff09;&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小 ii.&数组名&#xff0c;这里的数组名表示整个数组&#xff0c;取出的是整个数组的地址 iii.除此之外&#xff0c;所…

基于urllib库的网页数据爬取

实验名称&#xff1a; 基于urllib库的网页数据爬取 实验目的及要求&#xff1a; 【实验目的】 通过本实验了解和掌握urllib库。 【实验要求】 1. 使用urllib库爬取百度搜索页面。 2. 使用urllib库获取百度搜索的关键字搜索结果&#xff08;关键字任选&#xff09;。 实验原理及…

电子元器件介绍——二极管(四)

电子元器件介绍 文章目录 电子元器件介绍前言一、二极管的基础知识二、二极管的分类三、二极管的应用总结 前言 这一节我们看一下二极管。 一、二极管的基础知识 PN结&#xff1a;是指一块半导体单晶&#xff0c;其中一部分是P型区&#xff0c;其余部分是N型区。 在电场作用…

C++ Qt开发:自定义Dialog对话框组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍自定义Dialog组件的常用方法及灵活运用。 在…

基于linux系统的Tomcat+Mysql+Jdk环境搭建(四)linux安装Mysql

1.切换到你需要安装mysql的路径 cd /root/usr/ 2.在线安装 安装网上的安装方式都有很多&#xff0c;可以自己百度一下 我们这里是自己搭建测试环境&#xff0c;可以直接选择在线安装&#xff0c;命令如下&#xff1a;yum install mysql-server&#xff0c; 但是我失败了 ┭┮…

在排序数组中查找元素的第一个和最后一个位置(Java详解)

一、题目描述 给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 示…

verilog语法进阶,时钟原语

概述&#xff1a; 内容 1. 时钟缓冲 2. 输入时钟缓冲 3. ODDR2作为输出时钟缓冲 1. 输入时钟缓冲 BUFGP verilog c代码&#xff0c;clk作为触发器的边沿触发&#xff0c;会自动将clk综合成时钟信号。 module primitive1(input clk,input a,output reg y); always (posed…

深度剖析JavaScript中冒泡和捕获机制、事件代理

JS事件传播的两种机制包括冒泡和捕获&#xff0c;下面将具体剖析它们之间本质的区别。 事件冒泡: 先触发子元素的事件&#xff0c;再触发父元素的事件。 创建一个 ul label 和 li label, 分别绑定一个父id 和 子 id, 再通过创建 script&#xff0c;去绑定各自的点击事件。 <…

Threejs利用着色器编写动态飞线特效

一、导语 动态飞线特效是可视化数据地图中常见的需求之一&#xff0c;鼠标点击的区块作为终点&#xff0c;从其他区块飞线至点击区块&#xff0c;附带颜色变换或者结合粒子动画 二、分析 利用创建3点来构成贝塞尔曲线&#xff0c;形成线段利用着色器材质来按照线段以及时间…

Linux---压缩和解压缩命令

1. 压缩格式的介绍 Linux默认支持的压缩格式: .gz.bz2.zip 说明: .gz和.bz2的压缩包需要使用tar命令来压缩和解压缩.zip的压缩包需要使用zip命令来压缩&#xff0c;使用unzip命令来解压缩 压缩目的: 节省磁盘空间 2. tar命令及选项的使用 命令说明tar压缩和解压缩命令 …

SE考研真题总结(三)

继续更新&#xff0c;今天准备连出两期该系列~ SE考研真题总结&#xff08;二&#xff09;https://blog.csdn.net/jsl123x/article/details/134857052?spm1001.2014.3001.5501 目录 一.简答题 二.代码大题 一.简答题 1.工程和科学的区别 科学是关于事物的基本原理和事实的…

代码随想录算法训练营 | day53 动态规划 1143.最长公共子序列,1035.不相交的线,53.最大子序和

刷题 1143.最长公共子序列 题目链接 | 文章讲解 | 视频讲解 题目&#xff1a;给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长公共子序列的长度。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下…

Android动画(四)——属性动画ValueAnimator的妙用

目录 介绍 效果图 代码实现 xml文件 介绍 ValueAnimator是ObjectAnimator的父类&#xff0c;它继承自Animator。ValueAnimaotor同样提供了ofInt、ofFloat、ofObject等静态方法&#xff0c;传入的参数是动画过程的开始值、中间值、结束值来构造动画对象。可以将ValueAnimator看…

C#深拷贝效率对比

对于浅拷贝和深拷贝&#xff0c;前面的文章已经说明了。 C#浅拷贝和深拷贝数据-CSDN博客 本篇说一下&#xff0c;深拷贝的效率问题&#xff0c;效率一直是程序追求的&#xff0c;效率越高肯定越好&#xff0c;有时候功能是实现了&#xff0c;但是运行以及处理数据的效率非常低…

【算法】bfs与dfs算法解决FloodFill(洪流)问题(C++)

文章目录 1. 什么是FloodFill问题2. 用什么方法解决FloodFill问题3. 具体例题773.图像渲染200.岛屿数量695.岛屿的最大面积130.被围绕的区域 1. 什么是FloodFill问题 一般floodfill问题可以描述为&#xff1a;给定一个二维矩阵&#xff0c;其中每个元素代表一个像素点&#xf…

Python-flask 入门代码

python与pycharm安装 过程略&#xff0c;网上很多&#xff0c;记得为pycharm配置默认解释器 虚拟环境 pipenv # 全局安装虚拟环境 # 可加-U参数&#xff0c;明确全局安装&#xff0c;不加好像也可以? pip3 install pipenv #检查安装情况 pipenv --version # ---控制台输出…

跨域的解决方式(java后端)

文章目录 一、跨域介绍1、什么是跨域2、为什么会产生跨域3、禁止跨域的原因 二、简单请求和非简单请求1、简单请求1.1、什么时简单请求1.2、简单请求基础流程 2、非简单请求2.1、预检请求2.2、预检请求的回应2.3、浏览器的正常请求和回应 3、自定义跨域过滤器 三、解决方式1、C…

Java基础语法之抽象类和接口

抽象类 什么是抽象类 并不是所有的类都是用来描述对象的&#xff0c;这样的类就是抽象类 例如&#xff0c;矩形&#xff0c;三角形都是图形&#xff0c;但图形类无法去描述具体图形&#xff0c;所以它的draw方法无法具体实现&#xff0c;这个方法就可以没设计成抽象方法&…

003 Windows用户与组管理

Windows用户管理 一、用户账户 1、什么是用户账户 不同用户身份拥有不同的权限每个用户包含了一个名称和一个密码每个用户账户具有唯一的安全标识符查看系统中的用户 net user 安全标识符&#xff08;SID&#xff09; whoami /user 使用注册表查看 打开注册表命令regedi…