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

        对于数组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++的学习进度还没到这一块,因此还没解决这个问题。

 

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

 

    夜深了,你在干嘛呢?

 

转载于:https://www.cnblogs.com/1242118789lr/p/6691144.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值