最大连续子串

问题描述:

给定一个由数字组成的数组,求出和最大的子数组

求解方法:

1.暴力法

选取所有连续和的可能性

#最大连续子序列,暴力法
l=[2,3,-9,3,2,1,-1,5,-9,1,2,3]
lo=0
hi=len(l) - 1
m=l[0]
for i in range(lo,hi+1):
	for j in range(i,hi+1):
		cursum=0
		for k in (i,j):
			cursum+=l[k]
		m=max(m,cursum)
print(m)

 由于i,j,k的范围都是[0,n],则时间复杂度为O(n^{3})

2.暴力优化

利用数组sum储存0-i项和,两次遍历sum数组得到连续和

#最大连续子序列,暴力法优化
l=[0,2,3,-9,3,2,1,-1,5,-9,1,2,3]#数组第一项为零防止越界
lo=1
hi=len(l) - 1
sum=[0]*len(l)
m = l[1]
for i in range(lo,hi+1):
	sum[i]=sum[i-1]+l[i]
for i in range(lo,hi+1):
	for j in range(i,hi+1):
		cursum = sum[j] - sum[i-1]#求i到j之间的连续和
		m = max(cursum,m)
print(m)

 由于sum数组的长度为n 所以时间复杂度为O(n^{2})

利用i,j来控制子数组的首尾项

#最大连续子序列,暴力法优化
l=[2,3,-9,3,2,1,-1,5,-9,1,2,3]
lo=1
hi=len(l) - 1
m = l[1]
#i为子序列首项,j为尾项
for i in range(lo,hi+1):
	sum = 0
	for j in range(i,hi+1):
		sum += l[j]
		m = max(m,sum)
print(m)

3.分治法

将问题分为两个子问题

1.最大子序列全部出现在左边或右边则递归解决

2.最大子序列横跨中点,将左半部分最大的连续和加上右半部分最大连续和相加即为最大连续和

#最大连续子序列,分治法
l=[1,-9,4,7,-1,2]
lo=0
hi=len(l)-1

def f(l,lo,hi):
	if lo==hi:
		return l[lo];
	mid = (hi-lo)//2 + lo
	m1 = f(l,lo,mid)
	m2 = f(l,mid+1,hi)
	left=l[mid]
	right=l[mid+1]
	now=0
	for i in range(mid,lo-1,-1):
		now+=l[i]
		left=max(now,left)
	now=0
	for i in range(mid+1,hi+1):
		now+=l[i]
		right=max(now,right)
	m3=left+right;
	return max(m1,m2,m3);
	
print(f(l,lo,hi))

4.分析法

因为最大 连续子序列和只可能是以位置0~n-1中某个位置结尾。当遍历到第i个元素时,判断在它前面的连续子序列和是否大于0,如果大于0,则以位置i结尾的最大连续子序列和为元素i和前门的连续子序列和相加;否则,则以位置i结尾的最大连续子序列和为元素i。

#最大连续子序列,分析法
l=[2,3,-9,3,2,1,-1,5,-9,1,2,3]
lo=0
hi=len(l) - 1
maxhere=maxsum= 0
for i in range(lo,hi+1):
	if maxhere<=0 :
		maxhere = l[i]
	else:
		maxhere+=l[i] 
		maxsum=max(maxhere,maxsum)
print(maxsum)

时间复杂度O(n)

5.动态规划

记s[i]是以a[i]结尾的最大子数组和

s[i+1]=max(s[i]+a[i+1],a[i+1])

s[0]=a[0];

遍历数组a[i]即可得到以每一项结尾的最大子数组和s[i],求出其中最大值

#最大连续子序列,动态规划
l=[2,3,-9,3,2,1,-1,5,-9,1,2,3]
lo=1
hi=len(l) - 1
s=[0]*len(l)#初始化字符串
s[0]=l[0]
for i in range(lo,hi+1):
	s[i]=s[i-1]+l[i]
	s[i]=max(s[i],l[i])
print(max(s))
		

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值