软件算法设计与分析 期中复习
第四章 蛮力法
- 定义:基于问题描述或者概念定义解决问题
蛮力法/多项式求值
最近点对问题
- 问题:给出平面上n个点,找出距离最近的两个点的距离
- 蛮力算法:求出所有点对的距离然后找出最小距离
- 时间效率: O(n2)
蛮力法的优缺点
- 优点
- 简单直观
- 应用广泛
- 算法正确性显然
- 缺点
- 算法效率低
- 对某些问题蛮力法只能解决较小规模的问题(穷举搜索)
旅行推销商问题
- 问题:给定n个城市,每对城市间都有路径相连,且知道每对城市的距离。一个推销商从一个城市出发,到达其他所有城市一次且仅一次,最后回到出发城市,问怎样规划路径使得其总路程最短?
背包问题
- 问题:有一个容量为W的背包和n件物品,每件物品:
- 大小: w1 w2 … wn
- 价值: v1 v2 … vn
- 在不超过背包容量的情况下,找出背包所装物品的最大价值
分配问题
- 问题:有n项工作需要分配给n个人完成,每人分配一项工作。为第i人分配第j项工作的成本是C[i,j]。需要找到一个分配方案,使得总成本最低
- 穷举法: 生成所有可能的分配方案,计算每种方案的成本,找出最低成本的方案.
- 共有多少种分配方案?
穷举法特点
- 穷举法在一些情形下只能解决较小规模的问题
- 一些问题具有比穷举法高得多的时间效率
- 最短路问题
- 最小生成树问题
- 分配问题
- 在很多情形下,一些问题的精确解只能通过穷举法或者其变种得到
第五章 分治法
5.1 分治法的基本思想
- 分而治之(divide-and-conquer)的设计思想是把一个难以下手的大问题,分割成一些较小的子问题,通过解决小问题最终解决大问题。具体是把一个输入规模为n的问题分割成k个子问题,1<k<=n,递归解决子问题,合并子问题的解求出原问题的解
- 许多问题可分为两个子问题( k等于2 ),并尽量让子问题的规模相同。子问题规模相同的做法是出自一种衡(balancing)子问题的思想。平衡子问题一般可提高算法平均情况下的时间效率也可简化算法的时间复杂性的分析
5.2 寻找最大值、最小值问题
-
问题:考虑从有n个元素的集合S中找出最大元和最小元问题
-
思想:
- 简单方法:先用(n-1)次比较,找出S中的最大元,然后在剩下的元素中用(n-2)次比较找出最小元。当n≥2时,共需要(2n-3)次比较
- 分治法:假定n是2的整次幂,把集合S分成两个不相交的集合S1和S2。分别找出两个子集中的最大元和最小元,再做比较即可求得S中的最大元和最小元
-
算法:minmax(A, low , high )
输入:数组A,下标low,上标high
输出: A[low… high]中的最小值和最大值(min , max)minmax(A, low , high): if high – low =1 if A[low] < A[high] then return (A [low], A[high]); else return (A[high], A[low]); else mid ← low+high)/2 ; //向下取整 (x1, y1 ) ← minmax(A, low, mid); (x2, y2 ) ← minmax(A, mid+1, high); x ← min(x1, x2); y ← max(y1, y2); return (x,y)
-
分析算法:
5.3 合并排序
-
算法:
输入:数组A,下标low,上标high
输出:数组A[low…high]升序排列MergeSORT(A, low, high): if high-low=1 then if A[low]>A[high] 交换A[low]和A[high]; Else mid= low+high)/2 MergeSORT (A, low, mid); MergeSORT (A, mid+1, high); MERGE (A, low, mid, high);
-
分析算法:
当n是2的次幂时,算法BottomUpSort和MergeSort所执行的元素比较次数是相同的,当n不是2的次幂时,两种算法需要的元素比较次数是接近的。它们的时间复杂性都是Θ(nlog n)
5.4 快速排序
-
思想:将集合S={a1,a2,……,an}分成小于a,等于a,大于a的三个子集合S1,S2,S3。分别将S1与S3递归排序,最后将S1,S2和S3连接起来
-
划分算法:Split(A,low,high)
输入:数组A,下标low,上标high, A[low]为划分元素
输出: A[low]已经在其正确位置的数组A及其新下标wSplit(A,low,high): i← low; x←A[low]; for j ← low+1 to high if A[j] <=x then i ← i+1; if i<>j then 交换A[i]和A[j]; 互换A[low]和A[i] w ← i; return A和w // 时间效率: Θ(n)
-
快速排序算法:QuickSort(A, low, high)
输入:数组A,下标low,上标high, A[low]为划分元素
输出:排好序的数值A[low…high]QuickSort(A, low, high): if high – low <= 1 then 将A中的元素直接排序; return(A); else if low < high (A , w) ← Split(A,low, high); quickSort(A, low, w-1); quickSort(A, w+1, high);
-
算法分析:
-
随机化快速排序: RandomQuicksort(A, low, high)
输入:数组A,下标low,上标high
输出:排好序的数值A[low…high]RandomQuicksort(A, low, high): if high – low <=1 then 将A中的元素直接排序; return(A); else if low< high v ← random(low, high); //从low…high中随机选择一个数 互换A[low]和A[v]; // A[v]为划分元素 (A,w) ← Split(A , low , high); RandomQuicksort(A, low, w-1); RandomQuicksort(A, w+1, high);
5.5 分治法的范式
- 对于简单实例直接求解(边界条件)
- 划分:分解原问题为多个子问题(子问题尽可能平衡)
- 治理:递归调用算法求解子问题
- 组合:合并各子问题的解得到原问题的解
大整数乘法
-
问题:对两个n(n>100)位十进制整数进行乘法运
-
思想:
-
[解法一]直接求解,需要做n2次位乘
-
[解法二]利用分治法求
-
- 算法分析:
矩阵乘法
-
问题:对两个n阶矩阵进行相乘
-
思想:
-
[解法一]直接求解,需要做n3次乘法
-
[解法二]利用分治法求解
-
Strassen矩阵乘法
最近点对问题
-
问题:给出平面上n个点 (x1,y1), (x2,y2)…(xn,yn),求这n个点中距离最近的两个点和其距离
-
思想:
- [解法一]蛮力法,计算出任意两点间距离,求最小值。时间复杂度为O(n2)
- [解法二]分治法,将n个点平分到2个集合A,B中,每个集合中
含有n/2个点,距离最近的点对有三种可能分布:- 集合A中
- 集合B中
- 点对一点在集合A,另外一点在集合B
- 可通过递归求得1和2两种情形结果,情形3可计算A中每点和
B中每点的最短距离得到,最后取三种情形的最小值
-
算法分析:
- 算法:
5.6 选择问题
-
问题描述:从n个元素中选择第k小的元素
-
思想:
- [方法一]将n个元素排序后,再寻找第k小元素
- [方法二]分治法:线性时间内找到第k小元素
- 找出n个元素的近似中位数mm
- 将n 个元素划分成三组A1,A2,A3: 所有小于mm的元素放入A1,等于mm的元素放入A2 ,大于mm的元素放入A3
- 通过计算每组的元素个数可判断第k小元素在哪一组中,通过递
归在该组中找出目标元素
-
算法:select(A, low, high , k)
输入:数组A,low<=k<=high
输出:第k小元素select(A, low, high , k): p ←high-low+1; if p<44 then 将A排序 return(A[k]); 令q= , 将A分成q组,每组5个元素,如果5不能整除A,则排除剩余元素 将q组中的每一组单独排序,找出中项,所有中项的集合为M mm ←select(M, 1, q, ) mm作为划分元素,将A分成3组,A1, A2,A3 Case |A1|>=k: return select(A1,1,|A1|,k) |A1|+|A2|>=k: return mm |A1|+|A2|<k: return select(A3,1,|A3|,k-|A1|-|A2|)
-
算法分析:
作业
坏球问题
- 原文链接:https://blog.youkuaiyun.com/wwlcsdn000/article/details/79456771
循环赛日程表问题
-
原文链接:https://blog.youkuaiyun.com/lhd1110/article/details/120725660
ROUND-ROBIN-CALENDAR-REC(A,n): if n == 1: then A[1][1] = 1 return ROUND-ROBIN-CALENDAR-REC(A,n/2) m=n/2 for i = 1 to m for j = 1 to m do A[i][j+m]=A[i][j]+m A[i+m][j]=A[i][j+m] A[i+m][j+m]=A[i][j]