在解决一些规模较大问题的时候通常无法直接解决,需要划分为多个规模较小的问题,这种思想就是分治(分而治之)的思想。

一.满足分治法的要求

首先,一个问题想要用分治法来解决,那么他需要满足一些基本要求

(1)该问题规模为n的问题的解可以分为k个规模较小的子问题的解

(2)这些子问题相互独立

(3)将子问题的解合并得到的就是对应原问题的解

二.分治法的基本步骤

(1)分:按照一定的规律和策略将原来的大问题分解为多个小问题

(2)递归:递归计算各个子问题的解

(3)合并:将所有子问题的解合并

三.分治法的计算效率的一般递归方程

T(n)=o(1)     n=1

T(n)=k*T(n/m)+f(n)   n>1


四.具体实例分析分治

1.二分

分治法的运用最简单的就是二分思想了(该算法太简单就不详细介绍了)

时间复杂度:每次将数组的规模缩小一般,时间复杂度o(logn)


2.大整数的乘法

在计算一些大整数的乘法的时候,如果我们根据小学列式计算的话时间复杂度为o(n^2),显然这样的复杂度难以满足时间的要求,所以数学家们开始研究,能不能降低时间复杂度

(1)初步优化

x,y为两个长度为n的大整数,我们将他们都分解为长度减半的大整数

x=ab

y=cd

那么x*y=(a*10^(n/2)+b)*(c*10^(n/2)+d)=ac*10^n+(ad+bc)*10^(n/2)+bd

这样的话分解为4次n/2整数的乘法+3次不超过2n的整数加法+2次位运算

T(n)=o(1)  n=1

T(n)=4*T(n/2)+o(n)  n>1

由master定理,这样的时间复杂度仍然是o(n^2),如果想要继续优化的话我们需要将系数4进一步减小

(2)实质性优化

有了目标,聪明的数学家又发动了聪明的大脑没进一步优化

x*y=ac*2^n+((a-b)*(d-c)+ac+bd)*2^(n/2)+bd

(*@ο@*) 哇~,乘法的次数变为了3次!!!

T(n)=o(1)  n=1

T(n)=3*T(n/2)+o(n)  n>1

由master定理算出此时的时间复杂度为o(n^(log3))=o(n^1.59)  

伟大的优化!!

3.合并排序

将带排序的元素分成为大小一致相同的两个子集和,分别对两个子集和进行排序,然后将两个已经排好序的子集和合并为所要求的排好序的集合

T(n)=o(1)  n=1

T(n)=2*T(n/2)+o(n)  n>1

时间复杂度为o(n*logn)

(*)自然合并排序

在上述排序算法中,最后我们合并的时候是合并长度为1的子数组段,但是其实在给定的序列有可能相邻的几个数已经是有序的,我们可以将这几个数看做一个子数组段,这样的话我们合并的时候次数就减少了,在某些特定的情况下

时间复杂度可以达到o(n)


4.矩阵乘法

矩阵乘法是线性代数中最常见的问题之一,按公式计算的话时间复杂度将会达到o(n^3)

(1)初步优化

分治思想小结

这样的话

T(n)=o(1)  n=2

T(n)=8*T(n/2)+o(n^2)  n>2

该解仍是o(n^3)(2)进一步优化

分治思想小结

此时

T(n)=o(1)  n=2

T(n)=7*T(n/2)+o(n^2)  n>2

解得T(n)=o(n^2.81),较普通算法有了很大的改进

(3)最好算法

目前最好的算法的时间复杂度的上界是o(n^2.376)

5.棋盘覆盖问题

分治思想小结分治思想小结分治思想小结分治思想小结分治思想小结分治思想小结分治思想小结分治思想小结分治思想小结

感觉该算法处理的还是非常巧妙,需要完全理解分治法的思想才行

T(n)=o(1)  n=0

T(n)=4*T(k-1)+o(1)  n>0

时间复杂度为o(4^k)(格子数)
完结

分类:

技术点:

相关文章: