【数据结构&&算法系列】最大子数组

购买股票的时候,我们都希望在较低价的时候买入,在较高价的时候卖出,来最大化收益。

股票的问题可以转化为最大子数组的问题,其中数组中的每个数字为相邻两天价格的差。

最大子数组需要找出连续的和最大的子数组。


最大子数组问题的解决可以通过分治的算法。找到数组的中间的数的位置,然后将数组划分为两个子数组,

下标范围分别是 0-p 和 p+1-n,n表示数组大小,分别递归求两个子数组的最大子数组,另外求跨越中间位置的最大子数组。

比较三个最大子数组中的最大值,作为最终的返回值。可以通过求解递归式(参考《算法导论》)可以得出该算法的时间复杂度为o(nlogn)。


代码

#coding : utf-8

def find_max_crossing_subarray(arr,low,mid,high):
	max_left_sum = float("-inf")
	max_left = mid
	sum = 0
	for i in range(mid, low-1, -1):
		sum += arr[i]
		if sum > max_left_sum:
			max_left_sum = sum
			max_left = i

	max_right = mid
	max_right_sum = float("-inf")
	sum = 0
	for i in range(mid+1, high+1):
		sum += arr[i]
		if sum > max_right_sum:
			max_right_sum = sum
			max_right = i
	return (max_left,max_right,max_left_sum+max_right_sum)

def find_max_subarray(arr,low,high):
	if low == high:
		return (low,high,arr[low]) # base case: only one element
	else:
		mid = (low+high)/2
		(left_low,left_high,left_sum) = find_max_subarray(arr,low,mid)
		(right_low,right_high,right_sum) = find_max_subarray(arr,mid+1,high)
		(cross_low,cross_high,cross_sum) = find_max_crossing_subarray(arr,low,mid,high)

		if max(left_sum,right_sum,cross_sum) == left_sum:
			return (left_low,left_high,left_sum)
		elif max(left_sum,right_sum,cross_sum) == right_sum:
			return (right_low,right_high,right_sum)
		else:
			return (cross_low,cross_high,cross_sum)

def show_max_subarray(arr,low,high):
	print "[", ", ".join([str(x) for x in arr[low:high+1]]), "]"

if __name__ == "__main__":
	arr = [13, -3, -25 , 20, -3 , -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
	low,high,sum_v = find_max_subarray(arr,0,len(arr)-1)
	print low,high,sum_v
	show_max_subarray(arr,low,high)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值