算法设计与分析--求最大子段和问题(蛮力法、分治法、动态规划法) C++实现

2023-11-17

算法设计与分析--求最大子段和问题

问题描述:

给定由n个整数组成的序列(a1,a2, …,an),求该序列形如

的子段和的最大值,当所有整数均为负整数时,其最大子段和为0。


利用蛮力法求解:

int maxSum(int a[],int n)
{
	int maxSum = 0;
	int sum = 0;
	for(int i = 0; i < n; i++) //从第一个数开始算起
	{
		for(int j = i + 1; j < n; j++)//从i的第二个数开始算起
		{
			sum = a[i];
			a[i]  += a[j];
			if(a[i] > sum)
			{
				sum = a[i];		//每一趟的最大值
			}
		}
		if(sum > maxSum)
		{
			maxSum = sum;
		}

	}
	return maxSum;
}


利用分治法求解:

int maxSum(int a[],int left, int right)
{
	int sum = 0;
	if(left == right)	//如果序列长度为1,直接求解
	{
		if(a[left] > 0) sum = a[left];
		else sum = 0;
	}
	else 
	{
		int center = (left + right) / 2;	//划分
		int leftsum = maxSum(a,left,center);	//对应情况1,递归求解
		int rightsum = maxSum(a, center + 1, right);//对应情况2, 递归求解
		int s1 = 0;
		int lefts = 0;
		for(int i = center; i >= left; i--)	//求解s1
		{
			lefts += a[i];
			if(lefts > s1) s1 = lefts;	//左边最大值放在s1
		}
		int s2 = 0; 
		int rights = 0;
		for(int j = center + 1; j <= right; j++)//求解s2
		{
			rights += a[j];
			if(rights > s2) s2 =rights;
		}
		sum = s1 + s2;				//计算第3钟情况的最大子段和
		if(sum < leftsum) sum = leftsum;	//合并,在sum、leftsum、rightsum中取最大值
		if(sum < rightsum) sum = rightsum;
	}
	return sum;
}


利用动态规划法求解:

int DY_Sum(int a[],int n)
{
	int sum = 0;
	int *b = (int *) malloc(n * sizeof(int));	//动态为数组分配空间
	b[0] = a[0];
	for(int i = 1; i < n; i++)
	{
		if(b[i-1] > 0)
			b[i] = b[i - 1] + a[i];
		else
			b[i] = a[i];
	}
	for(int j = 0; j < n; j++)
	{
		if(b[j] > sum)
			sum = b[j];
	}
	delete []b;		//释放内存
	return sum;
}





完整测试程序:

#include<iostream>
#include<time.h>
#include<Windows.h>
using namespace std;
#define MAX 10000

int BF_Sum(int a[],int n)   
{
	int max=0;     
	int sum=0;        
	int i,j;
	for (i=0;i<n-1;i++)        
	{         
		sum=a[i];          
		for(j=i+1;j<n;j++)            
		{       
			if(sum>=max)                
			{                                         
				max=sum;                
			}  
			sum+=a[j];         
		}    
	}    
	return max;
}    
int maxSum1(int a[],int left, int right)
{
	int sum = 0;
	if(left == right)	//如果序列长度为1,直接求解
	{
		if(a[left] > 0) sum = a[left];
		else sum = 0;
	}
	else 
	{
		int center = (left + right) / 2;	//划分
		int leftsum = maxSum1(a,left,center);	//对应情况1,递归求解
		int rightsum = maxSum1(a, center + 1, right);//对应情况2, 递归求解
		int s1 = 0;
		int lefts = 0;
		for(int i = center; i >= left; i--)	//求解s1
		{
			lefts += a[i];
			if(lefts > s1) s1 = lefts;	//左边最大值放在s1
		}
		int s2 = 0; 
		int rights = 0;
		for(int j = center + 1; j <= right; j++)//求解s2
		{
			rights += a[j];
			if(rights > s2) s2 =rights;
		}
		sum = s1 + s2;				//计算第3钟情况的最大子段和
		if(sum < leftsum) sum = leftsum;	//合并,在sum、leftsum、rightsum中取最大值
		if(sum < rightsum) sum = rightsum;
	}
	return sum;
}

int DY_Sum(int a[],int n)
{
	int sum = 0;
	int *b = (int *) malloc(n * sizeof(int));	//动态为数组分配空间
	b[0] = a[0];
	for(int i = 1; i < n; i++)
	{
		if(b[i-1] > 0)
			b[i] = b[i - 1] + a[i];
		else
			b[i] = a[i];
	}
	for(int j = 0; j < n; j++)
	{
		if(b[j] > sum)
			sum = b[j];
	}
	delete []b;		//释放内存
	return sum;
}

int main()
{
	int num[MAX];
	int i;
	const int n = 40;
	LARGE_INTEGER begin,end,frequency;
	QueryPerformanceFrequency(&frequency);
	//生成随机序列
	cout<<"生成随机序列:";
	srand(time(0));
	for(int i = 0; i < n; i++)
	{
		if(rand() % 2 == 0)
			num[i] = rand();
		else
			num[i] = (-1) * rand();
		if(n < 100)
			cout<<num[i]<<" ";
	}
	cout<<endl;

	//蛮力法//
	cout<<"\n蛮力法:"<<endl;
	cout<"最大字段和:";
	QueryPerformanceCounter(&begin);
	cout<<BF_Sum(num,n)<<endl;
	QueryPerformanceCounter(&end);
	cout<<"时间:"
		<<(double)(end.QuadPart - begin.QuadPart) / frequency.QuadPart
		<<"s"<<endl;

	cout<<"\n分治法:"<<endl;
	cout<"最大字段和:";
	QueryPerformanceCounter(&begin);
	cout<<maxSum1(num,0,n)<<endl;
	QueryPerformanceCounter(&end);
	cout<<"时间:"
		<<(double)(end.QuadPart - begin.QuadPart) / frequency.QuadPart
		<<"s"<<endl;

	cout<<"\n动态规划法:"<<endl;
	cout<"最大字段和:";
	QueryPerformanceCounter(&begin);
	cout<<DY_Sum(num,n)<<endl;
	QueryPerformanceCounter(&end);
	cout<<"时间:"
		<<(double)(end.QuadPart - begin.QuadPart) / frequency.QuadPart
		<<"s"<<endl;

	system("pause");
	return 0;
}

测试结果:



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

算法设计与分析--求最大子段和问题(蛮力法、分治法、动态规划法) C++实现 的相关文章

随机推荐

  • [ACM] 1016 Prime Ring Problem (深度优先搜索)

    Prime Ring Problem Problem Description A ring is compose of n circles as shown in diagram Put natural number 1 2 n into
  • Linux-3种方法快速找出监听特定端口的进程

    Pre 端口是代表通信端点的逻辑实体 并与操作系统中的给定进程或服务相关联 在之前的文章中 我们解释了如何找出 Linux 中所有开放端口的列表 以及如何使用 Netcat 命令检查远程端口是否可达 在这个简短的指南中 我们将展示在 Lin
  • TypeScript 中如何使用 getter 和 setter

    使用 get 和 set 关键字在 TypeScript 中定义 getter 和 setter getter 使我们能够将属性绑定到在访问属性时调用的函数 而 setter 将属性绑定到在尝试设置属性时调用的函数 class Develo
  • Qt助手(assistant):方便查找Qt类

    一个方便查找QT类用法的地方 QT自带的 QT助手 在qt安装路径中找到assistant exe 它就是QT助手 运行之后就可以查找QT中的类和函数了 找到后 将其发送到桌面快捷方式 更名为Qt助手
  • 关于pytorch图像处理模块的数据处理

    文章参考 chsasank github io from future import print function division import torch import torch nn as nn import torch optim
  • egg-jwt egg jwt 使用

    1 安装egg jwt npm install egg jwt save 2 配置 config plugin ts import EggPlugin from egg const plugin EggPlugin jwt enable t
  • MySQL数据库之DDL操作

    1 数据库管理系统的一些常用术语 学习数据库首先要清楚数据库的一些常用术语 行 又叫做记录 每一行都是一组相关的数据 列 又叫做字段 每一列都是一组数据类型相同数据 主键 是唯一的 在一张数据表中只有一个主键 且不能为空 外键 主要用于关联
  • 【牛客101】06,07判断链表中是否有环,找到环的入口

    文章目录 1 判断是否有环 1 1 题目描述 1 2 题目分析 1 3 代码讲解 2 找到环的入口 2 1 题目描述 2 2 问题分析 2 3 代码详解 1 判断是否有环 1 1 题目描述 判断给定的链表中是否有环 如果有环则返回true
  • JAVA中“+”加号用法总结及注意事项

    用法总结 1 若加号左右两边都是数值型时 做的是加法运算 2 若加号左右两边有任一方是非数值型时 做的都是拼接运算 注意事项 若加号左右两侧为方法名时将各方法结果输出后拼接打印 lo setAge 18 lo setName lou Sys
  • 关闭套接字close还是shutdown

    close 这个函数会对套接字引用计数 1 一旦发现引用计数到0 就会对套接字进行彻底释放 并且会关闭tcp两个方向的数据流 因为套接字可以被多个进程共享 你可以理解为我们给每个套接字都设置了一个积分 如果我们通过fork的方式创建了子进程
  • 软件工程导论习题

    软件工程是软件工程专业的一门重要学科 掌握好软件工程原理是开发软件的重要基础知识 本博客对软件工程导论部分习题解释 以更加深理解 选择 1 业界存在三种需求分析方法 面向功能分析 面向对象分析和 B A 面向算法分析 B 面向数据分析 C
  • 使用ESP定律_手工脱壳

    ESP定律脱壳一般的加壳软件在执行时 首先要初始化 保存环境 保存各个寄存器的值 一般利用PUSHAD 相当于把所有寄存器都压栈 当加壳程序的外壳执行完毕以后 再来恢复各个寄存器的内容 通过跨区段的转移来跳到程序的OEP来执行原程序 简单点
  • lr(1)分析法 算数表达式 c语言,编译原理及技术期末考试复习试题整理

    2 1 考虑文法G S 其产生式如下 S L a L L S S 1 试指出此文法的终结符号 非终结符号 终结符号为 a 非终结符号为 S L 开始符号为 S 2 给出下列各句子的分析树 a a a a a a a a a a 3 构造下列
  • Ubuntu20.04 开机无法进入登陆界面,一致转圈圈解决方案

    昨天把一个新的主机装了显卡驱动 cudnn没装完就关机走人了 今天早上一开机发现显示了这个 我没拍照片 这里盗用别的博主的照片了 搜了一下 本着能省则省的原则先从最简单的情况试起 怀疑是Lightdm出了问题 借用一下博主原话 是安装了li
  • 机器视觉开源代码集合

    机器视觉开源代码集合 一 特征提取Feature Extraction SIFT 1 Demo program SIFT Library VLFeat PCA SIFT 2 Project Affine SIFT 3 Project SUR
  • (struts2学习篇)struts2文件上传

    第一步 编写相关相关文件上传Action public class UploadFileAction extends ActionSupport private static final long serialVersionUID 1L 相
  • Hive千亿级数据倾斜解决方案

    数据倾斜问题剖析 数据倾斜是分布式系统不可避免的问题 任何分布式系统都有几率发生数据倾斜 但有些小伙伴在平时工作中感知不是很明显 这里要注意本篇文章的标题 千亿级数据 为什么说千亿级 因为如果一个任务的数据量只有几百万 它即使发生了数据倾斜
  • 十种经典运放电路分析

    转载十一种经典运放电路分析 本文章为转载文章 只是为以后方便查阅 如有侵权 请联系本人 1 反向放大器 图一运放的同向端接地 0V 反向端和同向端虚短 所以也是0V 反向输入端输入电阻很高 虚断 几乎没有电流注入和流出 那么R1和R2相当于
  • python解决Net Frameword匹配问题及Failed building wheel for XXX

    文章目录 1 背景 2 错误描述 2 1 错误关键语句 1 2 2 错误关键语句 2 2 3 错误关键语句 3 3 原因 4 解决问题 5 总结 6 参考链接 1 背景 计划使用NI veristand的python依赖包 但是在安装的过程
  • 算法设计与分析--求最大子段和问题(蛮力法、分治法、动态规划法) C++实现

    算法设计与分析 求最大子段和问题 问题描述 给定由n个整数组成的序列 a1 a2 an 求该序列形如 的子段和的最大值 当所有整数均为负整数时 其最大子段和为0 利用蛮力法求解 int maxSum int a int n int maxS