434
社区成员
发帖
与我相关
我的任务
分享主要思想:将完整的序列一分为二(下面称左段右段),分别求两段子序列的最大字段和来求解。最后结果会有三种情况:
(1)整个序列的最大子字段(s)与左段最大子字段(s1)相同
(2)整个序列的最大子字段(s)与右段最大子字段(s2)相同
(3)整个序列的最大子字段(s)恰好横跨左右段,即左右段的最大子字段是整个序列最大子字段的子字段(s=s1+s2)
伪代码如下:
def maxSum(a, left, right):
sum = 0
#结束递归的条件
if left == right:
if left > 0:
sum = left
else
sum = 0
else:
center = (left + right) / 2
#求左、右两段的和
leftSum = maxSum(a, left, center)
rightSum = maxSum(a, center + 1, right)
s1 = 0 #记录左段最大字段和
l = 0
for i = center; i >= left; i--:
l += a[i]
if l > s1:
s1 = l;
s2 = 0 #记录右段最大字段和
r = 0
for i = center; i >= left; i--:
r += a[i]
if r > s2:
s2 = r;
#对比三种情况,取最大的和
sum = s1 + s2
if s1 > sum:
sum = s1
if s2 > sum:
sum = s2
return sum
算法将每个问题分解为2个原问题规模1/2的子问题,合并子问题的时间复杂度为O(n)
因此T(n) = 2 * T(n/2) + O(n)
由主定理可以得到T(n) = O(n*log n)
分治法的主要思想为:
将一个大问题不停分割为k个子问题,如果子问题的规模仍然很大,就继续分割,直到子问题的规模易于求解为止;完成子问题的求解后,自底向上,将子问题合并为原问题。
分治法有以下几点特征:
1.可以将原问题转化为若干个独立的子问题
2.给个子问题的解最终可以合并为原问题的解
使用分治法时的解题步骤:
1.分解原问题:将原问题分解为若干个相同类型的子问题
2.求解子问题:利用递归或者迭代的方法,解决每个子问题,当子问题规模足够小时,可以直接得到答案
3.合并子问题:将每个子问题的解合并
分治法的时间复杂度分析:
假设算法将每个问题分解为a个b/n规模的子问题,合并子问题的时间复杂度为O(n^d),则
时间复杂度:T(n) = aT(n/b) + o(n^d)
利用主定理可以将T(n)化为:
O(n^d) , d > logb a
T(n) = O(n^d * log n) , d = logb a
O(n ^ logb a) , d < logb a
分治法的主要运用:
1.二分搜索
基本思想:将n个元素分成个数大致相同的两半,取a[n/2]与x作比较。如果x=a[n/2],则找到x,算法终止;如果x<a[n/2],则只在数组的左边部分继续搜索x,反之只在右边部分继续搜索x。
时间复杂度:O(log n)
2.快速排序
基本思想:
①分解:以a[p]为基准元素,将a[p:r]划分为三段, a[p:q-1]、a[q]、a[q+1:r],使得a[p:q-1]中的所有元素都小于a[q],a[q+1:r]中的所有元素都大于a[q],下标 q在划分过程中确定。
②递归求解:通过递归调用快速排序算法,分别对a[p:q-1]和a[q+1:r]进行排序。
③合并:由于算法直接对原序列就地进行,所以在a[p:q-1]和a[q+1:r]都排好序后就已经的到了最终结果。
时间复杂度:O(n*log n)