求最大子数组的思想和代码

对于数组ai,最大子数组定义为:ai的和最大的非空连续子数组,很明显,这个概念只对既有正元素,又有负元素的数组有意义,例如,对于ai[16] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7},最大子数组为{18, 20, -7, 12},此时的和为43,求解一个数组的最大子数组的算法依然是使用分治思想,把一个数组一分为二,最大子数组要么在左边,要么在右边,要么在中间,在中间则肯定包含中点,此时便可以从中点的左边和右边分别求出最大子数组的边界,合起来便是最大子数组,然后递归的调用此方法,便可求出原数组的最大子数组。

代码如下:

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
using namespace std;

int* find_max_crossing_subarray ( vector<int> &ci, unsigned low, unsigned mid, unsigned high); //函数返回数组的指针
int* find_maximum_subarray (vector<int> &ci, unsigned low,  unsigned high);

//函数返回数组的指针
//函数的功能为寻找横跨中点的最大子数组的小标和和,并组成一个数组返回
int* find_max_crossing_subarray ( vector<int> &ci, unsigned low, unsigned mid, unsigned high)
{
	int *temp = new int[3];   //为防止局部变量内存被释放掉,采用动态分配内存
	int left_sum = -1000;
	int right_sum = -1000;
	int sum = 0;
	unsigned max_left = 0;
	unsigned max_right = 0;
	for (int i = mid; i >= 0 && i >= low ; --i)
	{
	     sum =  sum + ci[i];
		 if(sum > left_sum )
		 {
		     left_sum = sum;
			 max_left = i;
		 }
	}
	sum = 0;

	for (unsigned j = mid + 1; j <= high; ++j)
	{
	     sum =  sum + ci[j];
		 if(sum > right_sum )
		 {
		     right_sum = sum;
			 max_right = j;
		 }
	}

	temp[0] =  max_left;
	temp[1] =  max_right;
	temp[2] =  left_sum + right_sum;
	return temp;

 }

//函数返回数组的指针
//函数的功能为寻找一个数组的最大子数组的下标和和
int* find_maximum_subarray (vector<int> &ci, unsigned low,  unsigned high)
{
	int *temp_1 = new int[3];   //为防止局部变量内存被释放掉,采用动态分配内存
	if (low ==  high)
	{
	    temp_1[0] =  low;
		temp_1[1] =  high;
		temp_1[2] =  ci[low];
		return temp_1;
	}
	else
	{
		 int mid = (low + high) / 2;
		int *temp_left = new int[3];
		int *temp_right = new int[3];
		int *temp_cross = new int[3];
	    temp_left= find_maximum_subarray(ci, low,mid);
		temp_right= find_maximum_subarray(ci, mid+1,high);
		temp_cross= find_max_crossing_subarray ( ci, low,mid,high) ;
		if (temp_left[2] > temp_right[2] && temp_left[2] > temp_cross[2] )
		{
		return temp_left;
		}
		else
		{
		    if ( temp_right [2] > temp_left[2]  && temp_right[2] > temp_cross[2] )
			{
			     return temp_right;
			}
			else
			{
			    return temp_cross;
			}
		}

	}
}

int main ()
{
   vector<int> ai;
    int num = 0;
    cout << "please enter the numbers that need to find the maximum subarray:" << endl;
    while (cin >> num )
        ai.push_back(num);

	int* maximum_subarray = find_maximum_subarray(ai,0,ai.size () - 1);
	cout << maximum_subarray[0] << "\t"
		    << maximum_subarray[1] << "\t"
			<< maximum_subarray[2] << "\t"
			<< endl;
	delete[] maximum_subarray;

  return 0;
}

  运行结果为:

上述结果表示为最大子数组为ai[7]到ai[10],此时和为43。

上述代码可能存在内存分配的问题,C++的学习进度还没到这一块,因此还没解决这个问题。

不得不说算法的力量是无穷的,或者说思想的力量是伟大的。

夜深了,你在干嘛呢?

时间: 2024-10-11 06:09:29

求最大子数组的思想和代码的相关文章

一维数组求最大子数组(解决溢出问题)

一.题目要求 题目:返回一个整数数组中最大子数组的和. 要求: 要求程序必须能处理1000 个元素: 每个元素是int32 类型的: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 二.设计思想 程序在宏里面定义出了数组长度的大小,在长度超过100万的时候程序直接崩溃,其实这并不是因为结果太大导致的数值溢出,而是因为内存溢出,我们的数组是定义在程序内部的,属于局部变量,存放位置在栈上

结对开发--四实现循环二维数组求最大子数组的和

一.实现思路 再上一个实验基础上加上环,我们实现环的思想是每一列依次向此替换,直至替换出能出现的所有的二维数组,再用上一个求最大子数组的方法全部实现 二.实验代码 package com.minirisoft; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.util.Scanner; public class HuanTwoArray { public stat

大数溢出数组求最大子数组

题目: 返回一个占内存较多的数组的最大子数组. 要求: 两人结对完成编程任务. 一人主要负责程序分析,代码编程. 一人负责代码复审和代码测试计划. 思想: 老师要求主要是解决内存溢出问题,所以我写的只是一种测试,可能和题目不符,但思路应该一样,就是把大数字一分为二,就像计算机中的高八位低八位一样,我假设一个数字最大表示范围为0~100,如果想要表示9856,那么就用98后面的跟上56来表示,然后高位有正负,求最大子数组,将结果放大相应倍数 加上对应的低位数字 程序源代码: #include<io

结对开发——环形一维数组求最大子数组和

题目:返回一个整数数组中最大子数组的和.要求:(1)输入一个整形数组,数组里有正数也有负数.(2)数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.(3)如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大.(4)同时返回最大子数组的位置.(5)求所有子数组的和的最大值.要求时间复杂度为O(n).一.设计思想 这个问题的最优解一定是以下两种可能.可能一:最优解没有跨过array[n-1]到array[0],即和非环形数

一维数组头尾相连求最大子数组

题目: 返回一个整数数组中最大子数组的和. 要求: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大. 同时返回最大子数组的位置. 求所有子数组的和的最大值.要求时间复杂度为O(n). 1. 设计思想: 因为已经写过了一维数组的求最大子数组程序.所以只是在原程序上进行修改.首先产生随机数数组,然后进行计算,因为要求时间复杂度

二维数组求最大子数组

设计思路: 首先定义产生二维数组,定义可输入二维数组行和列,各位数随机产生: 然后进行最大子数组的求和比较,从每行的第一个数为子数组的起点开始进行不同的子数组遍历比较,只存放最大的子数组,以及记录最大子数组的位置,从第一个数开始每行每列进行求和比较,以求得最大子数组的值,以及最大子数组所包含的数: 最后进行结果的输出与验证. 代码: 法一: package zishuzu; import java.util.*; public class zuixiaozishuzu { public stat

课堂作业:首尾相连求最大子数组

1.设计思想 先将数组环拆解补在原来数组后面,再依次找子数组并相加,更新最大值,并需要将开始的负数舍去从正数开始算起,单独讨论全负情况. 2.源程序 package zishuzu; import java.util.Scanner; public class zsz { public static void main(String[] args) { System.out.println("请输入数字个数:"); Scanner in=new Scanner(System.in);

数组问题之求最大子数组问题(一)

结束了 四则运算的所有内容 这次老师布置了 数组问题 求最大子数组的问题 课堂上 老师就已经提供了数种方案 并提出了时间复杂度的要求 于是和我的搭档找到了认为最为简便的算法 过程中和小于0,那么和最大的子数组不会包含前面子数组,之后将和归0,从下个元素重新开始计算 于之前的实验 理清思路 代码实现不算太难 代码如下 1 #include<iostream> 2 using namespace std; 3 4 int main() 5 { 6 int i,num; 7 cout <<

结对——二维数组首尾相连求最大子数组和

一.题目与要求 题目.返回一个二维整数数组中最大子数组的和 要求.1.输入一个二维整形数组,数组里有正数也有负数. 2.二维数组首尾相接,象个一条首尾相接带子一样. 3.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和 二.设计思路 在上一次的以为循环数组的基础上,和二维数组求最大子数组相结合,将功能合并,完成题目要求. 第一步.将每一行的数组作为循环数组求最大子数组 第二步.通过枚举的方式,将每一种情况的和存入到新建二维数组中 第三部.通过逐列计算最大子数组的方法求所有子矩阵的最