最大子数组问题及C语言实现


对于一个连续的数组a[n],要求连续子数组,使得该子数组的和最大。比如数组{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7},最大子数组为{18,20,-7,12},和为32。


方法一:穷举法。即将任取数组中的两个元素,算出两者之间(包括这两个元素本身)所有元素之和。穷举所有组合,比较得到最大值。该方法复杂度为n的三次方。

#include 
#include 

int sort(int *,int,int);

main()
{
	int a[16] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
	printf("%d\n",sort(a,0,15));
}

int sort(int *a,int low,int high)
{
	int i,j,k,sum,max_sum;
	
	max_sum = INT_MIN;

	for (i = low;i <= high;i++) {
		for (j = low+1;j <= high;j++) {
			sum = 0;
			for (k = i;k <= j;k++) {
				sum += a[k];
			}
			if (sum > max_sum)
				max_sum = sum;
		}
	}
	return max_sum;
}

方法二:递归法。以数组中间元素为分界,将整个数组分为左边的数组和右边数组。那么最大子数组有三种情况,分别是完全位于左数组,完全位于右数组以及横跨中间元素的数组。分别对左右数组进行递归,得到最终答案。该方法复杂度为nlgn。

#include 
#include 


int find_max_crossing_subarray(int *,int,int,int);//横跨左右数组的最大子数组
int find_maximum_subarray(int *,int,int);//返回最大子数组的和

main()
{
	int a[16] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
	printf("%d\n",find_maximum_subarray(a,0,15));
}

int find_max_crossing_subarray(int *a,int low,int mid,int high)
{
	int left_sum = INT_MIN;
	int right_sum = INT_MIN;
	int sum,i;

	sum = 0;//处理左数组
	for (i = mid;i >= 0;i--) {
		sum += a[i];
		if (sum > left_sum) {
			left_sum = sum;
		}
	}
	sum = 0;//处理右数组
	for (i = mid+1;i <= high;i++) {
		sum += a[i];
		if (sum > right_sum) {
			right_sum = sum;
		}
	}
	return left_sum + right_sum;
}
int find_maximum_subarray(int *a,int low,int high)
{
	int mid;
	int max_sum,max_sum1,max_sum2;
	max_sum = max_sum1 = max_sum2 = INT_MIN;

	if (high == low) {//元素数量为1的情况
		return a[low];
	} else {
		mid = (low + high) / 2;
		max_sum1 = find_maximum_subarray(a,low,mid);
		max_sum2 = find_maximum_subarray(a,mid+1,high);
		max_sum = find_max_crossing_subarray(a,low,mid,high);
		
		if (max_sum >= max_sum1 && max_sum >= max_sum2)
			return max_sum;
		else if (max_sum1 >= max_sum && max_sum1 >= max_sum2)
			return max_sum1;
		else
			return max_sum2;
	}
}

方法三: 当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。因此,当和为负数时,应该清零,并重新开始寻找最大子数组,当数组元素全为负数时,找到最大元素即可。

#include 
#include 

int line_sort(int *,int,int);

main()
{
	int a[16] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
	printf("%d\n",line_sort(a,0,15));
}

int line_sort(int *a,int low,int high)
{
	int i,sum,max_sum;
	int index_start,index_end;

	sum = 0;
	max_sum = INT_MIN;
	for (i = low;i <= high;i++) {
		sum += a[i];
		if (sum < 0) {
			sum = 0;
			index_start = i + 1;
		}
		if (sum > max_sum) {
			max_sum = sum;
			index_end = i;
		}
	}
	if (max_sum == 0) {
		max_sum = a[low];
		for (i = low + 1;i <= high;i++) {
			if (max_sum < a[i]) {
				max_sum = a[i];
				index_start = index_end = i;
			}
		}
	}

	printf("index_start:%d, index_end:%d \n",index_start,index_end);

	return max_sum;
}



你可能感兴趣的:(算法导论)