第2章递归与分治(new)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
wk.baidu.com
int temp;
temp = *a; *a = *b; *b = temp; }
temp = a;
a = b; b = temp; }
第2章 递归与分治策略
学习要点:
理解递归的概念。 掌握分治法的设计思想。 通过范例学习分治策略设计的技巧。
分治法的设计思想
任何利用计算机求解问题的计算时间都与输入数据的规模有关。 问题的规模较小,一般求解较容易。但有时直接解决一个较大问题, 是相当困难的。
一般的算法设计模式:
Divide-and-conquer(P) { if(|P|<n0 ) adhoc(P);
divede P into smaller subinstances p1,p2,…,pk;
for(i=1;i<=k; ++i) yi=Divide-and-conquer(Pi); return merge(y1,y2,…,yk); }
书籍推荐
Mooc 推荐
北大张铭老师《数据结构》
清华邓俊辉《数据结构》
coursera
学堂再线
stanford an introduction to algorithm coursera
内容补充
void swap(int a, int b){
int temp; void swap(int *a, int *b){
分治法的设计思想 将一个难以直接解决的大问题,分割成一些规模较小 的相同子问题。分而治之,以便各个击破。然后再利用这 些子问题的解,求出原问题的解。
§2.1 递归的概念
递归函数 用函数自身给出定义的函数。
递归算法 直接或间接调用自身的算法。
递归技术十分有用,使用递归技术往往使函数的定义和算法的描
述简捷且易于理解。
如何来表示q(n,m) ?
q(n,1)=1 q(n,m)=q(n,n) n>=1 m>=n (最大加数不能大于n) (n的划分由n1 =n的一种划分
和ni <=n-1的划分组成)
q(n,n) = 1+ q(n,n-1)
q(n,m)=q(n,m-1)+q (n-m, m) (n的划分由ni <=m-1的划分
例如
Fibonacci数列
Hanoi塔问题
二叉树的定义、遍历算法等
例一:整数划分问题
将正整数 n 表示成一系列正整数之和。 n = n1+ n2 +……+ nk
正整数n的不同划分个数称为正整数n的划分数,记作P(n)
整数划分问题就是求出P(n)。 分析:求 正整数 6 的划分数 n=6 n=3+3
和 n1=m, 其余加数ni <=m的划分组成
由此,设计计算q(n,m)的递归函数。 P(n)=q(n,n)
int q(int n, int m) { if((n<1)||(m<1)) return 0; if((n==1)||(m==1)) return 1; if (m>n) return q(n,n); if(m==n) return 1+q(n,m-1); return q(n,m-1)+q(n-m,m); }
例一:二分搜索技术
问题描述: 5 13 19 21 37 56 64 75 80 92 99
low
mid
high
5
13 19 21 37 56 64 75 80 92 99
void Permutation(int from, int to){
if(from == to){ int i; for(i = 0; i <= to; i++){ printf("%c",str[i]); } printf("\n"); return; } int i;
例二:排列问题 结果:
例二:排列问题 如何处理有重复的排列?例如:abbc
例二:排列问题 字符串的全排序问题描述:
给定字符串S[0„N-1],设计算法,枚举该字符串的
全排序。
如何设计该问题的递归算法?
例二:排列问题 递归算法:
以字符串abcd为例:
a – bcd
b – acd
c – abd d – abc 注意:保证每次递归前abcd顺序不变
例二:排列问题
char str[] = “abcd”; for(i = from; i <= to; i++){ swap(&str[i],&str[from]); Permutation(from+1,to); swap(&str[i],&str[from]); } } int main(){ Permutation(0,strlen(str)); return 0; }
n=1 n>1
T(n)=O(n2)
例一:二分搜索技术
问题描述:给定已排好序的n个元素a[0:n-1],要在这n个 元素中找到一特定元素x。 基本思想:在有序表中,取中间记录作为比较对象,若给 定值与中间记录的关键码相等,则查找成功;若给定值小 于中间记录的关键码,则在中间记录的左半区继续查找; 若给定值大于中间记录的关键码,则在中间记录的右半区 继续查找。不断重复上述过程,直到查找成功,或所有找 的区域无记录,查找失败。
分治法的所需的计算时间
O(1) T(n)= kT(n/m)+f(n) n>1 n=1
O(1) T(n)=
n=1
T(n)=O(nlogn)
2T(n/2)+ O(n) n>1
O(1) T(n)= 3T(n/2)+ O(n)
n=1 n>1
T(n)=O(nlog3)
O(1) T(n)= 4T(n/2)+ O(n)
a-bbc
b-abc
c-bba
注意:带重复字符的全排列就是每个字符分别与他 后面非重复出现的字符交换。
§2.2
分治法的基本思想
将一个规模为n的问题分解为k个规模较小的相同子问题,
这些子问题相互独立且与原问题相同。递归地这些子问题,
然后将子问题地解合并得到原问题的解。
问题一:把原问题分为多少个子问题才较合适? 问题二:子问题的规模是否相同最适当?
n=5+1
n=4+2
n=3+2+1
n=3+1+1
P(6)=11
n=4+1+1
…..
如何来表示递归关系?
记 q(n,m)为在 n 的所有不同划分中,最大加数ni不大于 m的划分数。 例如: q(6,1)=1 q(6,2)=4 即 6=1+1+1+1+1+1 即 6=2+2+2 6=2+2+1+1 6=2+1+1+1+1 6=1+1+1+1+1+1 q(6,6)=11
int temp;
temp = *a; *a = *b; *b = temp; }
temp = a;
a = b; b = temp; }
第2章 递归与分治策略
学习要点:
理解递归的概念。 掌握分治法的设计思想。 通过范例学习分治策略设计的技巧。
分治法的设计思想
任何利用计算机求解问题的计算时间都与输入数据的规模有关。 问题的规模较小,一般求解较容易。但有时直接解决一个较大问题, 是相当困难的。
一般的算法设计模式:
Divide-and-conquer(P) { if(|P|<n0 ) adhoc(P);
divede P into smaller subinstances p1,p2,…,pk;
for(i=1;i<=k; ++i) yi=Divide-and-conquer(Pi); return merge(y1,y2,…,yk); }
书籍推荐
Mooc 推荐
北大张铭老师《数据结构》
清华邓俊辉《数据结构》
coursera
学堂再线
stanford an introduction to algorithm coursera
内容补充
void swap(int a, int b){
int temp; void swap(int *a, int *b){
分治法的设计思想 将一个难以直接解决的大问题,分割成一些规模较小 的相同子问题。分而治之,以便各个击破。然后再利用这 些子问题的解,求出原问题的解。
§2.1 递归的概念
递归函数 用函数自身给出定义的函数。
递归算法 直接或间接调用自身的算法。
递归技术十分有用,使用递归技术往往使函数的定义和算法的描
述简捷且易于理解。
如何来表示q(n,m) ?
q(n,1)=1 q(n,m)=q(n,n) n>=1 m>=n (最大加数不能大于n) (n的划分由n1 =n的一种划分
和ni <=n-1的划分组成)
q(n,n) = 1+ q(n,n-1)
q(n,m)=q(n,m-1)+q (n-m, m) (n的划分由ni <=m-1的划分
例如
Fibonacci数列
Hanoi塔问题
二叉树的定义、遍历算法等
例一:整数划分问题
将正整数 n 表示成一系列正整数之和。 n = n1+ n2 +……+ nk
正整数n的不同划分个数称为正整数n的划分数,记作P(n)
整数划分问题就是求出P(n)。 分析:求 正整数 6 的划分数 n=6 n=3+3
和 n1=m, 其余加数ni <=m的划分组成
由此,设计计算q(n,m)的递归函数。 P(n)=q(n,n)
int q(int n, int m) { if((n<1)||(m<1)) return 0; if((n==1)||(m==1)) return 1; if (m>n) return q(n,n); if(m==n) return 1+q(n,m-1); return q(n,m-1)+q(n-m,m); }
例一:二分搜索技术
问题描述: 5 13 19 21 37 56 64 75 80 92 99
low
mid
high
5
13 19 21 37 56 64 75 80 92 99
void Permutation(int from, int to){
if(from == to){ int i; for(i = 0; i <= to; i++){ printf("%c",str[i]); } printf("\n"); return; } int i;
例二:排列问题 结果:
例二:排列问题 如何处理有重复的排列?例如:abbc
例二:排列问题 字符串的全排序问题描述:
给定字符串S[0„N-1],设计算法,枚举该字符串的
全排序。
如何设计该问题的递归算法?
例二:排列问题 递归算法:
以字符串abcd为例:
a – bcd
b – acd
c – abd d – abc 注意:保证每次递归前abcd顺序不变
例二:排列问题
char str[] = “abcd”; for(i = from; i <= to; i++){ swap(&str[i],&str[from]); Permutation(from+1,to); swap(&str[i],&str[from]); } } int main(){ Permutation(0,strlen(str)); return 0; }
n=1 n>1
T(n)=O(n2)
例一:二分搜索技术
问题描述:给定已排好序的n个元素a[0:n-1],要在这n个 元素中找到一特定元素x。 基本思想:在有序表中,取中间记录作为比较对象,若给 定值与中间记录的关键码相等,则查找成功;若给定值小 于中间记录的关键码,则在中间记录的左半区继续查找; 若给定值大于中间记录的关键码,则在中间记录的右半区 继续查找。不断重复上述过程,直到查找成功,或所有找 的区域无记录,查找失败。
分治法的所需的计算时间
O(1) T(n)= kT(n/m)+f(n) n>1 n=1
O(1) T(n)=
n=1
T(n)=O(nlogn)
2T(n/2)+ O(n) n>1
O(1) T(n)= 3T(n/2)+ O(n)
n=1 n>1
T(n)=O(nlog3)
O(1) T(n)= 4T(n/2)+ O(n)
a-bbc
b-abc
c-bba
注意:带重复字符的全排列就是每个字符分别与他 后面非重复出现的字符交换。
§2.2
分治法的基本思想
将一个规模为n的问题分解为k个规模较小的相同子问题,
这些子问题相互独立且与原问题相同。递归地这些子问题,
然后将子问题地解合并得到原问题的解。
问题一:把原问题分为多少个子问题才较合适? 问题二:子问题的规模是否相同最适当?
n=5+1
n=4+2
n=3+2+1
n=3+1+1
P(6)=11
n=4+1+1
…..
如何来表示递归关系?
记 q(n,m)为在 n 的所有不同划分中,最大加数ni不大于 m的划分数。 例如: q(6,1)=1 q(6,2)=4 即 6=1+1+1+1+1+1 即 6=2+2+2 6=2+2+1+1 6=2+1+1+1+1 6=1+1+1+1+1+1 q(6,6)=11