0x01算法设计与分析复习(一)习题解答
参考书籍:算法设计与分析——C++语言描述(第二版)
练习一
- 逆序输出正整数的各位数(递归算法求解)
#include <stdio.h> //逆序输出正整数的各位数(递归算法求解) void print(unsigned int n) { printf("%d", n%10);//基础情况 if(n>=10){ print(n/10);//递归部分 } } int main() { unsigned int n; scanf("%d", &n); print(n); return 0; }
实验结果:
123456 654321 Press any key to continue.
- 汉诺塔问题
//hanoi,汉诺塔问题求解 //将x柱上的n个圆盘经z柱移动到y柱上,任何时刻大盘不能在小盘上 #include <stdio.h> void move(int n, char x, char y)//将圆盘x从x移到y上 { printf("move %d from %c to %c\n", n, x, y); } void Hanoi(int n, char x, char z, char y)//将n个圆盘经z从x移到y { if(n>0){ Hanoi(n-1, x, y, z);//将n-1个盘从x移到z move(n, x, y);//将n盘从x移到y Hanoi(n-1, z, x, y);//将n-1个盘从z移到y } } int main() { int n = 0; char x = 'X', y = 'Y', z = 'Z'; scanf("%d", &n); Hanoi(n, x, z, y); return 0; }
实验结果:
3 move 1 from X to Y move 2 from X to Z move 1 from Y to Z move 3 from X to Y move 1 from Z to X move 2 from Z to Y move 1 from X to Y Press any key to continue.
- 排列产生算法
//排列产生算法 //给定n个自然数{0, 1, 2, ..., n-1},输出该集合所有可能的排列(permutation) #include <stdio.h> #include <stdlib.h> int i = 0; //arr[0]~arr[k-1]排好,求arr[k]到arr[n-1]的排列 void Perm(int arr[], int k, int n) { if(k == n-1){ for(int i = 0; i<n; i++) printf("%d ", arr[i]); printf("\n"); i++; } else if(k>=0){ //从arr[k]~arr[n-1]中拿出一个加入到已经排好的队中 for(int i = k; i<n; i++){ int tmp = arr[k]; arr[k] = arr[i]; arr[i] = tmp; Perm(arr, k+1, n); arr[i] = arr[k]; arr[k] = tmp; } } } int main() { int *arr = NULL, n = 0; scanf("%d", &n); arr = (int *)malloc(sizeof(int)*n); for(int i = 0; i<n; i++) arr[i] = i; Perm(arr, 0, n); printf("%d\n", i); return 0; }
实验结果:
3 0 1 2 0 2 1 1 0 2 1 2 0 2 1 0 2 0 1 6 Press any key to continue.
- 给出
n! 的递归定义式,并设计一个递归函数计算n!
/*n!的递归定义 n! = n*(n-1)!,n>0; n! = 1,n = 0; */ #include <stdio.h> int fact(int n) { if(n == 0) return 0; else if(n>1){ return n*fact(n-1); } } int main() { int n = 0; scanf("%d", &n); printf("%d\n", fact(n)); return 0; }
实验结果:
4 24 Press any key to continue.
- 写一个递归算法和一个迭代算法计算二项式系数:
Cmn=Cmn−1+Cm−1n−1=n!m!(n−m)!
#include <stdio.h> #include <stdlib.h> //递归算法 int func1(int n, int m) { if (m > n) return 0; if (n == m || m == 0) return 1; else if (n>0 && m>0) return func1(n - 1, m) + func1(n - 1, m - 1); } //迭代算法 int func2(int n, int m) { int i = 0, j = 0; int **record = (int **)malloc((n + 1) * sizeof(int *)); for (i = 0; i<n+1; i++) record[i] = (int *)malloc((m + 1) * sizeof(int)); //记录矩阵 for (i = 0; i<n + 1; i++) for (j = 0; j<m + 1; j++) { if (i < j) record[i][j] = 0; if (i == j || j == 0) record[i][j] = 1; else if (i >0 && j> 0) record[i][j] = record[i - 1][j] + record[i - 1][j - 1]; } return record[n][m]; } int main() { int n = 0, m = 0; scanf("%d %d", &n, &m); printf("%d\n", func1(n, m)); printf("%d\n", func2(n, m)); return 0; }
实验结果:
4 2 function 1: 6 function 2: 6 Press any key to continue.
- 给定一个字符串s和一个字符x,编写递归算法实现下列功能:
(1)检查x是否在s中
(2)计算x在s中出现的次数
(3)删除s中所有的x
/* 给定一个字符串s和一个字符x,编写递归算法实现下列功能: (1)检查x是否在s中 (2)计算x在s中出现的次数 (3)删除s中所有的x */ #include <stdio.h> #include <string.h> #include <stdlib.h> //检查x是否在s中 void XinS(char *s, char x) { if(s[0] != 0){ if(x == s[0]) printf("YES\n"); else { XinS(s+1, x); } } else printf("NO\n"); } //计算x在s中出现的次数 int CountX(char *s, char x) { int count = 0; if(s[0] != 0){ if(s[0] == x) count++; count += CountX(s+1, x); } return count; } //删除s中所有的x char *DelX(char *s, char x) { static int j = 0; static char tmp[100] = {'\0'}; if(s[0] != 0){ if(s[0] != x){ tmp[j++] = s[0]; } DelX(s+1, x); } else return tmp; } int main() { char x, s[100] = {'\0'}, *tmp; scanf("%s", s); getchar();//接收空字符; scanf("%c", &x); //(1) XinS(s, x); //(2) printf("%d\n", CountX(s,x)); //(3) tmp = DelX(s,x); memcpy(s, tmp, strlen(tmp)+1); printf("%s\n", s); return 0; }
实验结果:
asdfgts s YES 2 adfgt Press any key to continue.
- 写一个C++函数求解:给定正整数n,确定n是否是它所有因子之和
//写一个C++函数求解:给定正整数n,确定n是否是它所有因子之和 //因子就是所有可以整除这个数的数,不包括这个数自身 int ex7(unsigned int n) { int k=2, flag = n-1; while(k*k<n){ if(n%k == 0){ flag -= k; flag -= n/k; } k++; } if(k*k == n){ flag -=k; } return (flag==0); }
实验结果:
15 NO Press any key to continue.
- S是有n个元素的集合,S的幂集是S所有可能的子集组成的集合。例如,
S=a,b,c,则S的幂集=(),(a),(b),(c),(a,b),(a,c),(b,c),(a,b,c) 。写一个C++递归函数,以S为输入,输出S的幂集。
练习二
矩阵转置
(1)设计一个C/C++程序实现一个n×m 的矩阵转置。原矩阵保存在二维数组中。
(2)使用全局变量count,改写矩阵转置程序,并运行修改后的程序,以确定改程序的程序步
(3)计算此程序的渐进时间复杂度证明:若
f(n)=amnm+am−1nm−1+⋯+a1n+a0 是m 次多项式,且am>0 ,则f(n)=Ω(nm) .解:不妨令
c=12max{a0,a1,⋯,am},n0=2 ,当n≥n0 时,有
cg(n)≤12(nm+nm−1+⋯+n+1)≤12(nm+1−nm1−n)≤nm
根据定义有:f(n)=Ω(nm) 。运用主定理求
T(n)=2T(n/4)+n√,T(1)=3 的渐进界解:根据主定理,
a=2,b=4,f(n)=n√,log24=12 ,显然f(n)=n√=Θ(nlogab) ,所以
分类:
Algorithm
, Read_Notes
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)