分治算法/分治思想

本文深入介绍了分治算法的基本思想及其在排序(如快速排序、归并排序)、查找(如二分查找)等领域的应用。通过实例展示了如何用分治法解决最大值和最小值查找、汉诺塔问题。同时,文章提到了分治算法的优缺点,并探讨了当问题不具备合并条件时如何选择贪心算法或动态规划。最后,作者分享了一个二分查找的实现,但遇到了超时问题,邀请读者提供优化建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


分治算法的基本思想:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

分治算法的优缺点:

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


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


分治算法经典问题:

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

1 数组最大值和最小值

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

1.1 普通算法

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

#include<stdio.h>
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]<min)                    // 如果 min 小于遍历到的数字,则更新 min 的值
	        min = arr[i];
	}
	printf("max = %d, min = %d", max, min);                  // 输出 max 和 min 的值
	return 0;
 } 

1.2 分治算法

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

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


2 汉诺塔问题

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


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

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

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

3750: 二分查找

#include<stdio.h>
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(m<a[mid])  high = mid-1;
		else if(m>a[mid-1]) return mid;
		else low = mid - 1;
	}
	return 1;
}
int main()
{
	while(scanf("%d",&n)) //输入值…… 正常操作 
	{
		for(int i=0;i<n;i++)
		scanf("%d",&a[i]);
		scanf("%d",&m);
		if(a[0]==m) printf("1");
		else{
			int flag = BS(); // 插个旗子做记号 是否找到 
			if(flag == 1) //没找到 输出None 
			{
				printf("None\n");
			}
			else
				printf("%d\n",flag+1); //找到了输出flag+1 因为我们是从0开始记数的 
		}
	}
	return 0;
}

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


归并算法查找

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

5 快速排序算法

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值