最大连续子序列和 o(n)o(n*logn), o(n^2)空间复杂度的四种方法python实现

test_case = [1,4,3,-3,2,-5,-4,3,2,-8,4,5,-1]

在本文就使用上边的那个测试用例

下面是第一个方法,递推前缀和,时间复杂度o(n^2),思想很简单 把数组的从0到i的和求出来存到sums【i】,sum[i]计算的是test_case从0到i的和(不包括第i位),因此找出sums[i] - sums[j]最大就可以了.

def max_sum_1(test_case): 
	index_list = []
	max_sum = 0
	sums = [0 for i in range(len(test_case)+1)]
	for i in range(1,len(test_case)+1):
		sums[i] = sums[i-1]+test_case[i-1]   #sum[i]计算的是test_case从0到i的和(不包括第i位),因此找出sums[i] - sums[j]最大就可以了
	
	for i in range(len(test_case)+1):
		for j in range(i,len(test_case)+1):
			local_sum = sums[j]-sums[i]
			if local_sum >max_sum:
				max_sum = local_sum
				index_list.append((i,j-1,local_sum))

	if max_sum == 0:
		print("None")
	else:
		index_list = list(filter(lambda x:x[-1]==max_sum,index_list))
		print("the max_sum is %d" %max_sum)
		for index in index_list:
			local_list = test_case[index[0]:index[1]+1]
			print(local_list)

在我这里不止计算出了最终的和 我也把从哪儿到哪儿计算的打出来了,代码结果类似这样的。

#第二种o(n^2)的方法,i作为起点往后遍历顺便计算和。和前一种方法一样都是属于穷举

很简答就不多说了。

def max_sum_2(test_case):  
	index_list = []
	max_sum = 0

	for i in range(len(test_case)):
		local_sum = 0
		for j in range(i,len(test_case)):
			local_sum = local_sum+test_case[j]
			if local_sum>max_sum:
				max_sum = local_sum
				index_list.append((i,j,local_sum))

	if max_sum == 0:
		print("None")
	else:
		index_list = list(filter(lambda x:x[-1]==max_sum,index_list))
		print("the max_sum is %d" %max_sum)
		for index in index_list:
			local_list = test_case[index[0]:index[1]+1]
			print(local_list)

第三种是nlogn复杂度的,利用的是分治和递归的思想。具体就是把原数列切成两段。我们可以得到左边段的最大和,右边段的最大和,以及左边段包含最右的那个元素的最大和加上左边段包含最右那个数的最大和 的和,我们的目标就是这三者中最大的那个,然后不断的往上递归就OK了,思想类似与排序中的归并算法。

def max_sum_3(test_case,left,right):
	middle = int((left+right)/2)
	if left == right:
		if test_case[left] >0:
			return test_case[left]
		else:
			return 0 
	left_sum_max = max_sum_3(test_case,left,middle)
	right_sum_max = max_sum_3(test_case,middle+1,right)

	right_local_sum = 0
	right_local_sum_max = 0
	for i in range(middle+1,right+1):
		right_local_sum+=test_case[i]
		if right_local_sum > right_local_sum_max:
			right_local_sum_max = right_local_sum

	left_local_sum = 0
	left_local_sum_max = 0
	for i in range(middle - left +1):
		j = middle - i 
		left_local_sum += test_case[j]
		if left_local_sum>left_local_sum_max:
			left_local_sum_max = left_local_sum

	return max(left_local_sum_max+right_local_sum_max,left_sum_max,right_sum_max)

虽然这种算法不是最优的,但是 这种思想是很好的。

最后一种就是o(n)的时间复杂度的算法了,这种算法的思想是动态规划,它的操作是一段数组【a,b,c,d,e,f,g】
从前面往后加,如果后还是大于等于0 就继续,如果小于0就放弃之前的数值,然后从当前的下一位开始加,最后找到最大的数值就OK了

def max_sum_4(test_case):
	index_list = []
	current_sum = 0
	max_sum = 0
	start =0
	for i in range(len(test_case)):
		current_sum+=test_case[i]
		if current_sum>max_sum:
			max_sum = current_sum
			index_list.append((start,i,current_sum))
		if current_sum<0:
			current_sum = 0
			start = i+1

	if max_sum == 0:
		print("None")
	else:
		index_list = list(filter(lambda x:x[-1]==max_sum,index_list))
		print("the max_sum is %d" %max_sum)
		for index in index_list:
			local_list = test_case[index[0]:index[1]+1]
			print(local_list)

 从代码和执行过程分析思想:   【a,b,c,d,e,f,g】从前往后加 累计和小于0就一切从当前的下一位开始,current_sum值赋值0

我们发现加入加到第i位小于0那么tese_case[i]<0是必须的,所以往往第i位是小于0的,而它之前的值加起来都不足以抵消它因此我们就会抛弃之前的所有值。嗯嗯  有意思。

猜你喜欢

转载自blog.csdn.net/wqtltm/article/details/81288523