【算法导论学习】分治法求最大子数组

分治法

所谓分治法,就是把问题不断分割变小,常见的是把数组分割为两部分,然后分别计算,将大问题变成小问题。

问题分析方向

在这里插入图片描述
这一类问题主要用的是递归的方法,所以时间复杂度普遍为O(nlogn)

对时间复杂度的分析

在这里插入图片描述

样例分析

接下来分析最大子数组问题

问题分析

分解问题

求最大子数组无非就是求数组内某段连续的数相加,那么通过分治的思想,我们把问题拆开。

将一个数组变成两个数组,然后分别找两个数组中最大的子数组,然后再比较大小。

这么一想就会觉得问题简单了不少。但是仔细一想不对啊,要是最大子数组在两个部分中都有怎么办呢?,也就是在
于是这样我们就把问题分解为三个部分:
在这里插入图片描述

解决问题

对于仅位于两边的子数组来说好解决

  1. 在分解后的数组长度大于1的时候继续递归
  2. 要是到了递归尾了,那就直接输出最后剩下那一个数组元素就好了。

但是要是是中间那种情况怎么办呢?
这个好解决,要这么想,既然是经过最中间的元素,那么最大子数组里面必然包括最中间那个元素,那么直接从中间向两边遍历就好了。

通过不断累加计算寻找两边是否有更好的情况。
在这里插入图片描述

合并问题

对于某一个子数组来说,递归所返回的子数组就是最大子数组,其中返回的子数组就是目前这个某数组的最大子数组,因为返回的子数组就是从他的左边选出来的数组和右边选出来的子数组以及中间选出来的子数组中挑选的最大数组。
同理对于他的父数组来说也是这样。应该是类似于数学归纳法的想法。

对代码的设想

中间部分的处理
  1. 伪代码(来自算法导论)
    在这里插入图片描述
  2. C语言实现
mid_message find_mid(int A[], int low, int mid, int high)
{
   
   
	mid_message midx;
	int left_sum = -inf;
	int sum = 0;
	for(int i = mid ; i >= low ; i--)
	{
   
   
		sum = sum + A[i];
	    if (sum > left_sum)
	    {
   
   
	    	left_sum = sum;
	        midx.max_left = i;
		} 
	}
	
	int right_sum = -inf;
	sum = 0;
	for(int j = mid + 1 ; j <= high ; j++)
	{
   
   
		sum = sum + A[j];
		if (sum > right_sum)
	    {
   
   
	    	right_sum = sum
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值