栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

分治算法(D&C)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

分治算法(D&C)

文章目录
  • 概述
    • 例题1
    • 例题2
    • 例题3
  • 快速排序

概述

分治算法(Divide and Conquer, D&C),是一种经典的递归式解决问题的方法,分而治之,是其主要思想。
适用场景:
1)找到终止条件(基线条件),停止递归,条件越简单越好;
2)能将问题分解,不断地缩小问题规模,直至满足终止条件。
快速排序是采用分治思想的经典排序算法。
Talk is cheap, show me code.
将通过几个简单的小例子帮助理解,均使用python实现。

例题1
求数组之和,例如x = [1, 3, 2, 6, 5,7, 7, 9, 0, 0, 8], sum(x)=48 

首先,考虑能不能缩小问题规模,数组x包含多个元素,求和操作是一个累加操作,始终是两个元素进行相加,那么整个数组可以分解成多次的两个元素相加,此时问题的最小规模即为两个元素相加;
然后,考虑终止条件,数组x除了包含多个元素外,可能是空数组,也可能包含一个元素,如果是空数组,和为0,包含一个元素的数组,和为x[0]。

def dc_sum(num_list):
	if len(num_list) == 0:  # 终止条件
	    return 0
	elif len(num_list) == 1: # 终止条件
	    return num_list[0]
	else:
	    return num_list[0] + dc_sum(num_list[1:]) # 缩小问题规模
例题2
求数组最大值,例如x = [1, 3, 2, 6, 5,7, 7, 9, 0, 0, 8], max(x)=9

和求和类似,求最大值可以分解成始终是两个元素之间的比较,终止条件一样。

def dc_max(num_list):
	if len(num_list) == 0:  # 终止条件
	    return 0
	elif len(num_list) == 1: # 终止条件
	    return num_list[0]
	else:
		# 缩小问题规模
		tmp1 = num_list[0]
		tmp2 = dc_max(num_list[1:])
		if tmp1 > tmp2
			return tmp1
		else:
			return tmp2
例题3

有一块土地需要均匀的划分成方块,要求划分的方块要尽可能的大,求最大的方块边长,土地如下所示:

题目要求是方块,且尽可能的大,所以下图所示划分是不合理的:

设想一块土地是25x25的,那么符合条件的就是25x25的这样一个划分,如果是50x25呢,符合条件的就是划分出两个25x25的区域,也就是说,尽可能找到一个长宽能够整除的方块,这样才能保证划分的方块尽可能的最大。
但题目给的土地宽高并不能整除,怎么办呢?
可以先从土地中划分出两个640x640的区域,同时余下一块土地,对余下的这块土地采用相同的方式,划分出以最短边为方块的土地,然后再次余下一块土地,循环此操作,直到找到一个长宽能够整除的土地。





def dc_land_split(height, width):
	max_len = max(height, width)
	min_len = min(height, width)
	if max_len%min_len == 0: # 终止条件
		return min_len
	else:
		# 缩小问题规模
	    return dc_land_split(max_len%min_len, min_len) 
快速排序

快速排序算法是经典的排序算法之一,其平均运行时间为 O ( n l o g n ) O(nlogn) O(nlogn),最坏情况为 O ( n 2 ) O(n^2) O(n2)。
步骤:
1)选择一个基准值(pivot);
2) 将数组中其余的元素分成两个数组,小于pivot的放在一个数组,大于pivot的放在另一个数组,与pivot相等的放在其中任意一个数组,这样pivot就处于原始数组的中间位置。
3)重复2)操作,将两个数组分别进行排序。

上述步骤2)其实就是一个缩小规模的过程,逐渐的将原始数组进行不断分解成多个小数组,在分解的过程中实现了排序。
其终止条件即为数组中元素个数小于2个。

def quick_sort(num_list):
	if len(num_list) < 2:
		return num_list
	
	# pivot = num_list[0]
	pivot = num_list[len(num_list)//2]
	num_list.pop(len(num_list)//2)
	less = []
	greater = []
	for i in num_list:
		if i < pivot:
			less.append(i)
		else:
			greater.append(i)
	less = quick_sort(less)
	greater = quick_sort(greater)
	return less + [pivot] + greater

在取pivot时,如果去首元素作为基准值,那么最糟的情况即为对已经排序后的数组进行快排操作,那么始终有一子数组为空数组,此时其调用栈为 O ( n ) O(n) O(n),运行时间为 O ( n 2 ) O(n^2) O(n2),若取数组中间元素,其调用栈为 O ( l o g n ) O(logn) O(logn),运行时间 O ( n l o g n ) O(nlogn) O(nlogn)。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/311935.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号