求解最大子数组

        使用分治策略求解最大子数组,所谓分治策略就是将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解。分治策略在每层递归时都有三个步骤:

        1、分解原问题为若干子问题,这些子问题是原问题的规模较小的实例。

        2、解决子问题,递归的求解各子问题。当递归进入基准情况,则直接求解。

        3、合并这些子问题的解成原问题的解

        求解最大子数组,可以将其不断分解为更小的两个子数组,直至某个基准情况。则最大子数组要么在左子数组或在右子数组中,要么最大子数组跨越分解点各有一部分在左右子数组中。

           C代码如下:

/*使用分治方法求解最大子数组问题,时间复杂度为theta(n*lgn)
 * finde_max_crossing_subarray:寻找跨越中点的最大子数组
 * @param array 输入数组
 * @param low 输入数组的左边界
 * @param mid 输入数组的中点
 * @param high 输入数组的右边界
 * @return 返回最大子数组的边界和最大子数组的和
 * find_maximum_subarray:寻找最大子数组
 * @param array 输入数组
 * @param low 输入数组的左边界
 * @param high 输入数组的右边界
 * @return 返回最大子数组的边界和最大子数组的和
 */
typedef struct
{
	int low; //最大子数组的左边界
	int high; //最大子数组的右边界
	double sum; //最大子数组值的和
} region_sum;

region_sum find_max_crossing_subarray(double array[], int low, int mid, int high)
{
	region_sum result;
	double left_sum = array[low];
	double right_sum = array[mid + 1];
	double sum = 0;
	int max_left;
	int max_right;
	int i, j;

	for (i = mid; i >= low; i--)
	{
		sum += array[i];
		if (sum > left_sum)
		{
			left_sum = sum;
			max_left = i;
		}
	}

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

	result.low = max_left;
	result.high = max_right;
	result.sum = left_sum + right_sum;

	return result;
} // end find_max_crossing_subarray

region_sum find_maximum_subarray(double array[], int low, int high)
{
	region_sum result = {low, high, array[low]};
	region_sum result_left;
	region_sum result_right;
	int mid = (low + high) / 2;

	if (high == low)
	{
		return result;
	}
	else
	{
		result_left = find_maximum_subarray(array, low, mid);
		result_right = find_maximum_subarray(array, mid + 1, high);
		result = find_max_crossing_subarray(array, low, mid, high);

		if (result_left.sum >= result_right.sum 
				&& result_left.sum >= result.sum)
		{
			return result_left;
		}
		else if (result_right.sum >= result_left.sum 
				&& result_right.sum >= result.sum)
		{
			return result_right;
		}
		else
		{
			return result;
		}

	}
} //edn find_maximum_subarray

        测试如下:

printf("求解最大子数组测试\n");
	double subarray_test[16] = {13, -3, -25, 20, -3, -16, -23, 18, 
		20, -7,	12, -5, -22, 15, -4, 7};
	printf("array=");
	for (int i = 0; i < 16; i++)
	{
		printf("%lf ", subarray_test[i]);
	}		
	region_sum result;
	result = find_maximum_subarray(subarray_test, 0, 15);
        printf("\nThe maximum subarray index is %d from %d, and the sum	is %lf\n", 
                result.low, result.high, result.sum);	


参见《算法导论》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值