分治法自我总结

本文深入探讨了分治算法的基本思想、应用场景和特征,通过快速排序和寻找第K小元素为例,详细阐述了解题步骤及其实现。快速排序的平均时间复杂度为O(nlogn),而寻找第K小元素则是对快速排序的巧妙应用。通过对问题的分解、解决和合并,分治法在解决复杂问题时展现出高效性。
摘要由CSDN通过智能技术生成

分治法的主要思想:

将一个大问题不停分割为k个子问题,如果子问题的规模仍然很大,就继续分割,直到子问题的规模易于求解为止;完成子问题的求解后,自底向上,将子问题合并为原问题。(有动态规划的味道,但是很明显的区别就在于,分治法无法避免大量冗余的重复计算

分治法的应用场景,特征:

分治法的特征:

  1. 该问题可以被分割为一定规模后易于求解,并且可以分割为若干子问题;(分治法的基础)
  2. 子问题之间相互独立;
  3. 子问题解决后,合并起来可以得到原问题的解;
    (对比动态规划,可以发现,二者十分相似,但是关键点又有不同)

分治法的解题步骤:

1、分解:原问题分解为若干易于解决的子问题,注意:子问题应该与原问题属于同一类问题
2、解决:利用递归,解决子问题,当子问题规模足够小,直接一步得到答案;
3、合并:子问题合并为原问题;

分治法的主要例题:

不得不提的快速排序:

主要思想:

快速排序是分治思想贯彻最彻底的排序方法,每次选择一个支点,一轮排序后,该支点在整体数据的第几位就确定下来,十分有效的排序方法。

伪代码如下:

quick_sort( int * A , int p , int r )
{
	if ( p == r ) 
		return;
	//起始位置与终止位置相等,则返回;
	else
		int mid = partition ( A , p , r );
	//取得支点所在位置;
	quick_sort ( A , p , mid );
	quick_sort ( A , mid + 1 , r );
	//分治求解左右部分
}

int partition ( int *A , int p , int r ) {
	int x = A[p];//支点
	int i = p;//i记录下标
	for ( int j = p+1 ; j < r ; j++ ){
		if ( A[j] < x ) {
			i++ ;
			int temp = A[j];
			A[j] = A[i];
			A[i] = temp;
		}
	}
	int temp1 = A[i];
	A[i] = A[p];
	A[p] = temp;

	return i;
}

时间复杂度分析:

每次找到的支点,都是这一列数字中的中间元素,则
最优情况为O ( nlogn)
每次找到的支点,要么时最大值,要么是最小值,则
最坏情况:O(n^2)
经过一系列证明,平均复杂度还是O (nlogn)

过程演示:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一个partition的演示图

找到第K小元素:

主要思想:

基于快速排序的partition,可以轻松得到当前支点是数列中的第几个元素,用k与其进行比较,可以得到第k小元素。

伪代码:

kth_sort( int *A , int p , int r , int k ) {
	if ( p == r )
		return -1;//未找到
	else{
		int mid = partition ( A , p , r );
		//partition在快排中
		int i = mid - p + 1;// i 是A[i]的排名;
		if ( k == i )
			return A[i];
		else if ( k < i ) {
			return kth_sort ( A , p , mid-1 , k );
		}
		else if ( k > i ) {
			return kth_sort ( A , mid+1 , r , k-i );
		}
	}
}

时间复杂度

与快速排序保持一致;

中间的中间取得所有元素的中间大小元素:

详细的我也没有过深研究,大致的意思就是,将元素分割为5组,(可能有剩余成员,但是无伤大雅),每一组取其中间值,如下图;
在这里插入图片描述
然后在取出的5个中间元素中,再取出其中间值,这样就得到了整个数据的中间值:
在这里插入图片描述
很巧妙的一个方法,具体的代码我也没实现过,CSDN上有相应的代码,此处就不附上链接了。

总结:

分治算法是基础算法,其主要思想在后面的学习中会经常用到,需要我们重点掌握。还有很多例子还没列举出来,但是都可以理解为换汤不换药,都是分治思想的应用,熟悉掌握快速排序的思想,分治算法就解决了很大一部分了。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值