算法导论---分治1(分治概念和一些简单算法例子)

分治策略:

  • 将原始问题划分或者归结为规模较小的子问题
  • 递归或迭代求解每个子问题
  • 将子问题的解综合得到原问题的解

注:

  • 子问题与原问题性质完全一样
  • 子问题之间可彼此独立地求解
  • 递归停止时子问题可直接求解

算法的一般描述:
Divide-and-Conquer§

时间复杂度函数的递推方程:
W(n)=W(|P1|)+W(|P2|)+…+W(|Pk|)+f(n)
W(c)=C

  • P1,P2,…,Pk为划分后产生的子问题
  • f(n)为划分子问题以及将子问题的解,综合得到原问题解的总工作量
  • 规模为c的最小子问题的工作量为C

两类常见递推方程:

该类递推方程适用于子问题按常数项减少,其中i是每次划分的子问题大小,ai表示子问题的个数,g(n)为分解过程和综合解的工作量。求解可使用迭代法、递归树

该类递推方程适用于子问题按倍数缩小,其中b是缩小的倍数,a表示子问题的个数,d(n)为分解过程和综合解的工作量。求解可使用迭代法、换元法、递归树、主定理

当d(n)为常数:
a != 1,则T(n)=O(n^logba)
a = 1,则T(n)=O(logn)
当d(n)=cn,其中c为常数
a < b,则T(n)=O(n)
a = b,则T(n)=O(nlogn)
a > b,则T(n)=O(n^logba)

分治算法的优化
分治算法递推式:W(n)=aW(n/b)+f(n)或W(n)=aW(n-i)+f(n)

  1. 减少子问题数。即减少递推式的中a的大小,利用子问题间的依赖关系,是某些子问题的解通过组合其他子问题的解而得到。适用于子问题个数多,划分和综合的工作量不大,复杂度函数W(n)=Θ(n^logba)

例:输入:X,Y是n位二进制数,n=2k。输出:XY

普通乘法:O(n2)
划分:令X=A2n/2+B,Y=C2n/2+D
XY=AC2n+(AD+BC)2n/2+BD
优化前算法复杂度:W(n)=4W(n/2)+O(n)=O(n2),时间复杂度未发生变化
优化:AD+BC=(A-B)(D-C)+AC+BD,其中A-B和D-C都不会超过n/2位,AC和BD是原有的子问题
优化后算法复杂度:W(n)=3W(n/2)+O(n)=O(nlog3)

  1. 增加预处理。即减少递推式中f(n)的工作量

二分检索

设计思想:

  • 通过x与中位数比较,将原问题归结为规模减半的子问题,如果x小于中位数,则子问题由小于x的数构成,否则子问题由大于x的数构成
  • 对子问题进行二分检索
  • 当子问题规模为1时,直接比较x与T[m],若相等则返回m,否则返回0

算法:BinarySearch(T,l,r,x)
输入:有序数组T;下标从 l 到 r ;检索元素 x
输出:若 x 在T中,输出下标 j ;否则输出 -1

伪码:
在这里插入图片描述
c++:

#include<iostream>
using namespace std;

const int n = 10;
int T[n] = {
    -2, 0, 8, 13, 20, 29, 35, 44, 50, 58 };		//有序数组

int BinarySearch(int *T, int l, int r, int x){
   
	int m;
	while(l <= r){
   
		m = (l + r) / 2;
		if(T[m] == x){
   
			return m;
		}else if(T[m] > x){
   
			r = m - 1;
		}else{
   
			l = m + 1;
		}
	}
	return -1;
}

int main
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您解答算法导论第15章的双调欧几里得旅行商问题和整齐打印问题。 1. 双调欧几里得旅行商问题 双调欧几里得旅行商问题是指在平面上给定一些点,求一条简单闭合曲线,使得经过每个点恰好一次,且总路程最小。其中,欧几里得距离是指两点之间的距离。 该问题可以通过分治算法进行求解,具体步骤如下: 1)将所有的点按照x坐标从小到大排序; 2)将所有的点分成两部分,分别求出每一部分的最小路径,分别记为d1和d2; 3)在两部分的点中,选择一个点p,使得p在上一部分的最后一个点,同时p在下一部分的第一个点; 4)以p为分界点,将所有点分成上下两部分,并分别按照y坐标从小到大排序; 5)分别计算上半部分和下半部分的最小路径,分别记为d3和d4; 6)最终结果为d1+d2+d3+d4。 2. 整齐打印 整齐打印问题是指将一段文本分成若干行,每行不超过给定的宽度,使得每一行的长度尽可能相等,同时在每行末尾添加空格,使得每行的末尾恰好是一个单词的末尾,且每行的空格数最小。 该问题可以通过动态规划算法进行求解,具体步骤如下: 1)定义一个cost数组,其中cost[i][j]表示将第i个单词到第j个单词放在一行的代价; 2)定义一个lc数组,其中lc[i][j]表示将第i个单词到第j个单词放在一行的空格数; 3)计算cost和lc数组,具体方法如下: - 对于任意的i<=j,将第i到第j个单词放在一行,计算该行的空格数; - 如果该行的长度超过给定的宽度,则该方案不可行,否则将该方案的代价和空格数存入cost和lc数组中。 4)定义一个dp数组,其中dp[i]表示将前i个单词分成若干行的最小代价; 5)动态规划求解dp数组,具体方法如下: - 对于任意的1<=i<=n,将前i个单词分成若干行,计算最小代价; - 设最后一行的单词范围为[j+1, i],则dp[i] = min(dp[j] + cost[j+1][i]),其中j的范围为0<=j<i。 6)最终结果为dp[n]。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值