分治策略实例
1.1 中位数选取问题
算法步骤
- 设输入规模为n,则先将其分为n/5组
- 在每一组(5个元素)中选出其中位数。
每组插入排序选出中位数,其比较次数为10次。共比较10 ⌈ n 5 ⌉ \lceil \frac{n}{5} \rceil ⌈5n⌉次 - 在 ⌈ n 5 ⌉ \lceil\frac{n}{5}\rceil ⌈5n⌉中递归调用算法,时间复杂度为 T ( n 5 T(\frac{n}{5} T(5n,得到MoM(中位数的中位数)
- 在经过比较n-1次,将其它元素分为:小于MoM,等于MoM和大于MoM的情况,然后再挑选合适的组别递归调用算法。
伪代码
Int Select(A,i){
/*
Input:数组A[1:n],1<=i<=n
Output:A中第i位数
*/
for j=1 to n/5:
InsertSort(A[5*(j-1)+1,5*(j)]);
A[j]=Swap(A[j],A[5*(j-1)+3]);
mom = Select(A[1:n/5],n/10);
k=partirion(A[1:n],mom);
if k==i then return mom;
else if k>i then return Select(A[1:k-1,i]);
else return Select(A[k+1,n],i-k)
}
算法分析
- 通过选取MoM作为划分子问题的中间界限,则每次至少有 ⌊ 3 n 10 ⌋ − 6 \lfloor{\frac{3n}{10}}\rfloor-6 ⌊103n⌋−6规模的元素被分于MoM的两侧。因此在递归调用解决子问题时,子问题的规模不超过 ⌊ 7 n 10 ⌋ + 6 \lfloor{\frac{7n}{10}}\rfloor+6 ⌊107n⌋+6
- 故 T ( n ) = { Θ ( 1 ) , n < c T ( ⌊ 7 n 10 ⌋ + 6 ) + T ( ⌊ n 5 ⌋ ) + Θ ( n ) , n ≥ c T(n)=\begin{cases}\Theta(1),&n<c\\T(\lfloor\frac{7n}{10}\rfloor+6)+T(\lfloor \frac{n}{5}\rfloor)+\Theta(n),&n\ge {c}\end{cases} T(n)={Θ(1),T(⌊107n⌋+6)+T(⌊5n⌋)+Θ(n),n<cn≥c
- 最后可证T(n)=O(n).
1.2 最大子数组问题
分治策略
-
对于有正有负的数组A[1:n],选取mid= ⌊ n 2 ⌋ \lfloor\frac{n}{2}\rfloor ⌊2n⌋(为了分得更为平均),可以得到A[1:mid],A[mid+1,n]
-
同样对于A[low,high],可分为A[low,mid],A[mid+1,high]两数组。
-
则对于A[low,high],其最大连续子数组必然为以下三种情况之一:
- 完全位于A[low,mid]中。
- 完全位于A[mid+1,high]中。该两种情况可以用递归解决
- 跨越了中点。该种情况可以在O(n)时间复杂度下解决。
伪代码
Tuple Find_Maximum_Subarray(A,low,high){
/*
Input:数组A[low:high].初始调用时为A[1:n],n>1
Output:三元组(max_left,max_right,max_sum)
*/
if low==high:
return (low,high,A[low])
mid = (high-low)/2
(left_low,left_high,left_sum)= Find_Maximum_Subarray(A,low,mid)
(right_low,right_high,right_sum) = Find_Maximun_Subarray(A,mid+1,high)
(crossing_low,crossing_high,crossing_sum) = Find_Crossing_Subarray(A,mid)
if left_sum>=right_sum>=crossing_sum:
return (left_low,left_high,left_sum)
else if right_sum>=left_sum>=crossing_sum:
return (right_low,right_high,right_sum)
else:
return (crossing_low,crossing_high,crossing_sum)
}
寻找跨越终点的最大子数组不再赘述,暴力迭代n次即可
算法分析
- T ( n ) = { Θ ( 1 ) , n < c , 2 T ( n 2 ) + Θ ( n ) , n ≥ c , T(n)=\begin{cases}\Theta(1),&n<c,\\2T(\frac{n}{2})+\Theta(n),&n\ge{c},\end{cases} T(n)={Θ(1),2T(2n)+Θ(n),n<c,n≥c,
- 故 T ( n ) = Θ ( n l o g n ) T(n)=\Theta(nlogn) T(n)=Θ(nlogn)