分治算法/分治思想

学习参考来自:lloil的分治算法详解 和 编程帮的分治算法


分治算法的基本思想:

        将一个问题分解为n个相互独立且与原问题性质相同的子问题,通过逐个解决小问题,从而解决整个问题。(逐个击破,分而治之

分治算法/分治思想_第1张图片

分治算法是很多高效算法的基础:

        排序算法:快速排序、归并排序、堆排序……

        查找算法:二分查找(折半查找算法)……

        傅立叶变换:快速傅立叶变换……

        各类问题:大整数乘法、棋盘覆盖、汉诺塔……

采用分治算法能解决问题有以下特征: 

  • 原问题规模大,不易解决。但原问题可缩小且到一定程度就可以容易解决。

绝大多数问题都可以满足的,问题的计算复杂性一般是随着问题规模的增加而增加。

  • 原问题可以分解为多个规模较小、求解方式相似的子问题。且各个子问题之间相互独立、互不影响。

这是应用分治算法的前提,绝大多数问题都可以满足的,反映了递归思想的应用。

  • 若干子问题的解进行合并后,可以得到原问题的解。

这是应用分治算法的关键,能否利用分治法完全取决于问题是否满足这点。

如果仅仅具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心算法或动态规划。

  • 原问题所分解出的各个子问题是相互独立的。

这与分治算法的效率相关,如果子问题不是相互独立的,那么采用动态规划较好。

分治算法的优缺点:

        分治算法主要用于解决规模较大的问题,通过将大问题“分而治之”将有效降低题目难度。又因为分解得到的子问题之间是相互独立且互不影响的,所以可以同时进行,以此提升解决问题的效率。
        分治算法的缺陷在于,分治算法常常采用递归的方式实现,整个过程需要消耗大量的系统资源,严重时还会导致程序崩溃。


        分治重要的是一种思想,注重的是问题分、治、合并的过程。在分治算法中,递归是一种通过方法调用自身形成一个回路的过程,而分治可能就是利用了多次这样的来回过程。


分治算法经典问题:

       因为分治算法重要在于理解其思想,还有一些典型的分治算法解决的问,所以博主在这里主要讲述数组最大值和最小值、汉诺塔问题、二分查找算法、归并算法查找、快速排序算法。

1 数组最大值和最小值

        数组最大值和最小值问题:是指在长度为 n 的数字序列中找到最大的数和最小的数。

1.1 普通算法

        普通算法中:定义两个变量 max 和 min 并将序列中首个数字赋值给他们,从第 2 个数字开始遍历整个序列,如果遍历到的数字比 max 大,将其赋值给 max,如果遍历到数字比 min 小,将其赋值给 min。整个序列遍历完成后,max 记录的是序列中最大的数字,min 记录的是序列中最小的数字。

#include
int main()
{
	int n;
	scanf("%d",&n);
	int arr[n];  
	for(int i=1;i<=n;i++) // 输入 n 个数字
	{
		scanf("%d",&arr[i]);
	}
	int max,min;
	max = min = arr[1];   // 将第 1 个数字分别赋值给 max 和 min 
	for(int i=2;i<=n;i++)
	{                  // 从第 2 个数字开始遍历
	    if(arr[i]>max)                    // 如果 max 小于遍历到的数字,则更新 max 的值
	        max = arr[i];
	    if(arr[i]

1.2 分治算法

        对于本问题,分治算法就是不断地进行二分,直到分解为不可分的一个数组元素,这个数组元素是最小子问题的最大值也是最小值,之后再逐一合并为原问题的解。

        具体的分治算法可参考:王陸的算法设计与分析——分治法求最大值和最小值


2 汉诺塔问题

        请参考博主写的:汉诺塔(Hanoi) ——递归思想


3 二分查找算法(折半查找算法)

        二分查找又称折半查找,是一种基于分治思想的快速搜索算法,时间复杂度为O(logn)
        二分查找算法只适用于有序序列,换句话说,只有保证序列有序的情况下,才能使用二分查找算法。

        二分查找的搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

3750: 二分查找

#include
int n,m,a[1000001]; //全局变量 
//二分查找(Binary Search) 确认 是否存在 所寻找的值 m 的函数 
int BS(){ 
	int low,mid,high; //二分查找 
	low = 0; high = n-1; //确定位置 
	while(low<=high) //进行寻找操作 
	{
		mid = (low+high)>>1; //>>1 和 /2 操作是一样的 不过网上说>>1的效率高一点 
		if(m>a[mid]) low = mid+1;
		else if(ma[mid-1]) return mid;
		else low = mid - 1;
	}
	return 1;
}
int main()
{
	while(scanf("%d",&n)) //输入值…… 正常操作 
	{
		for(int i=0;i

        但是博主交上去之后TLE了,不是很懂该怎么改,不想直接用库函数,求大佬指导一下。


归并算法查找

        归并排序是一种基于分治思想的排序算法,时间复杂度为O(nlogn),效率仅次于快速排序算法

5 快速排序算法

        快速排序(简称“快排”)是一种基于分治思想实现的排序算法,它具有排序效率高、消耗资源少、容易实现等优点,是很多实际场景的首选排序算法。

你可能感兴趣的:(算法,分治算法)