最大子数组问题

最大子数组问题

问题描述: 寻找数组A[1…n]和最大的非空连续子数组。

  • 条件: 数组中必须含有负数,不然将毫无意义,因为最大子数组将就是数组A本身。
  • 思想:分治思想。
    • 假设我们要求A的子数组A[low, high]的最大子数组。根据分治策略,我们先将A[low,high] 平分
    • 那么 A[low,highj]的子数组A[i,j]只有三种可能
      • a: 完全位于A[low, mid]; 此时 low <= i <= j <= mid
      • b: 完全位于A[mid+1, high]中,此时 mid + 1 <= i <= j <= high
      • c: 跨越了中点mid, 此时 low <= i <= mid < j < high
    • 对于 a 和 b 情况,仍然是最大子数组问题,可递归求解。
    • 只需要计算 c 类情况。
  • 步骤
    • 计算 c 类情况
/**
 * @title	findMaxCrossingSubarray
 * @description	寻找最大子数组问题中的寻找过中点的最大子数组函数
 * 总体理念: 对于给定的数组, 其中点坐标mid, 即向左寻找到最大子数组和, 再向右寻找到最大子数组, 返回左右边界及整个数组即可
 * 空间复杂度: O(n)
 * 时间复杂度: O(n)
 * @auth: ncuwen
 * @param: A	原数组
 * @param: low	数组起始下标
 * @param: high	数组末尾下标
 * @param: mid	数组中点下标, 有 low <= mid <= high
 * @return: 返回一个下标元组划分跨越中点的最大子数组的边界, 并返回最大子数组中值的和
 */
func findMaxCrossingSubarray(A []int, low int, mid int, high int) (int, int, int) {
	leftSum := constants.INT_MIN
	maxLeft := mid
	sum := 0
	for i := mid; i >= low; i-- {
		sum += A[i]
		if sum > leftSum {
			leftSum = sum
			maxLeft = i
		}
	}
	rightSum := constants.INT_MIN
	maxRight := mid + 1
	sum = 0
	for j := mid + 1; j <= high; j++ {
		sum += A[j]
		if sum > rightSum {
			rightSum = sum
			maxRight = j
		}
	}
	return maxLeft, maxRight, leftSum + rightSum
}
  • 求解最大子数组问题的分治算法
/**
 * @title	FindMaxSubarray
 * @description	寻找最大子数组
 * 总体理念: 分治思想
 * 空间复杂度: O(n)
 * 时间复杂度: O(nlg(n))
 * @auth: ncuwen
 * @param: A	原数组
 * @param: low	数组起始下标
 * @param: high	数组末尾下标
 */
func FindMaxSubarray(A []int, low int, high int) (int, int, int){
	if high == low {
		return low, high, A[low]
	} else {
		mid := (low + high) / 2
		leftLow, leftHigh, leftSum := FindMaxSubarray(A, low, mid)
		rightLow, rightHigh, rightSum := FindMaxSubarray(A, mid + 1, high)
		crossLow, crossHigh, crossSum := findMaxCrossingSubarray(A, low, mid, high)
		if leftSum >= rightSum && leftSum >= crossSum {
			return leftLow, leftHigh, leftSum
		} else {
			if rightSum >= crossSum {
				return rightLow, rightHigh, rightSum
			} else {
				return crossLow, crossHigh, crossSum
			}
		}
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值