【说人话的算法小课堂】使用分治法求最大连续子序列的和

使用分治法求最大连续子序列的和

设有一个整数数列a[n],1≤s, t≤n。求a[n]的一个子数列a[s, t],使得该子数列的和尽可能大。
若这个和小于0,则输出0。

【算法本体】

(参考代码中,因为要与暴力法对比运行时间,而暴力法用到前缀和,为了方便,数组下标从1开始)
设m = floor((s + t) / 2)。
当n = 1时,直接取唯一的元素作为结果。若该元素为负,则输出0。
当n > 1时,分3种情况讨论:
【情况1】该子数列完全落在原数列的左半部分a[s, m]。递归对数列a[s, m]求其最大连续子序列的和。
【情况2】该子数列完全落在原数列的右半部分a[m + 1, t]。递归对数列a[m + 1, t]求其最大连续子序列的和。
【情况3】该子数列横跨左右两部分,则【情况1】和【情况2】中的递归求解算法无法求出此类连续子数列的最大和。对此类子数列,只需要从中点m开始向两侧分别累加每个元素直到数列两端,就求得了此种连续子数列的最大和。
最后,针对3种情况求出的连续子序列的和,选取最大的作为最终结果。

【时间复杂度】

在该算法中,如果对长为n的数列求其最大连续子数列的和,那么需要对左右两段长为n / 2的子数列递归求解,再将递归求解无法顾及的横跨左右两半的子数列求解。所以
T(1)=O(1),n=1
T(n)=2T(1/2 n)+O(n),n>1
解得T(n) = O(n log n)。
与暴力算法对比:
暴力算法的过程是先算出原数组的前缀和(前n项和),然后通过
S_n-S_(n-1)=a_n
枚举S_n,S_(n-1)来考察所有连续子序列的和。时间复杂度为O(n^2)。
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/COFACTOR/article/details/108691530
今日推荐