1.基础知识2.练习题
2.1 n的阶乘2.2 x和y的最大值2.3 最大公约数2.4 交换数值2.5 打印数字2.6 打印矩阵2.7 递归求阶乘2.8 递归求斐波那契数列2.9 绝对值2.10 两个数的和2.11 区间求和2.12 最小公倍数2.13 复制数组2.14 打印字符串2.15 数组翻转2.16 数组去重2.17 数组排序2.18 跳台阶2.19 走方格2.20 排列
1.基础知识1.函数调用自己叫递归
2.函数数组传递属于引用传递,也就是说,修改函数数组里的数值会发生改变;
3.函数在传二维数组的时候,列数一定要写。因为二维数组在存储的时候是连续的一段空间,数组名相当于行指针(行信息),如果不告诉计算机列数(列信息),那和一维数组没有什么区别。如果告诉了,计算机就会知道面对一段连续的数组怎么划分行和列。
输入一个整数 n,请你编写一个函数,int fact(int n),计算并输出 n 的阶乘。
输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数表示 n 的阶乘的值。
数据范围
1≤n≤10
输入样例:
3
输出样例:
6
#include2.2 x和y的最大值using namespace std; int fact(int n) { if(n == 1) return 1; else { return n * fact(n - 1); } } int main() { int n; cin >> n; int res = fact(n); cout << res << endl; return 0; }
输入两个整数 x 和 y,请你编写一个函数,int max(int x, int y),计算并输出 x 和 y 的最大值。
输入格式
共一行,包含两个整数 x 和 y。
输出格式
共一行,包含一个整数,表示两个数中较大的那个数。
数据范围
−100≤x,y≤100
输入样例:
3 6
输出样例:
6
#include2.3 最大公约数using namespace std; int max(int x, int y) { if(x >= y) return x; else return y; } int main() { int x, y; cin >> x >> y; cout << max(x, y) << endl; return 0; }
输入两个整数 a 和 b,请你编写一个函数,int gcd(int a, int b), 计算并输出 a 和 b 的最大公约数。
输入格式
共一行,包含两个整数 a 和 b。
输出格式
共一行,包含一个整数,表示 a 和 b 的最大公约数。
数据范围
1≤a,b≤1000
输入样例:
12 16
输出样例:
4
//求最大公约数有个简便的方法,叫转展相除法 #include2.4 交换数值using namespace std; int gcd(int a, int b); int main() { int a, b; cin >> a >> b; cout << gcd(a, b) << endl; return 0; } int gcd(int a, int b) { int tmp; if(a >= b) tmp = b; else tmp = a; for(int i = tmp; i > 0; i --) { if(a % i == 0&& b % i == 0) return i; else continue; } }
输入两个整数 x 和 y,请你编写一个函数,void swap(int &x, int &y), 交换两个整数的数值并输出交换后的 x 和 y。
输入格式
共一行,包含两个整数 x 和 y。
输出格式
共一行,包含交换后的 x 和 y。
数据范围
1≤x,y≤100
输入样例:
3 5
输出样例:
5 3
#include2.5 打印数字using namespace std; void swap(int &x, int &y) { int tmp; tmp = x; x = y; y = tmp; return; } int main() { int x, y; cin >> x >> y; swap(x, y); cout << x << " " << y; return 0; }
输入一个长度为 n 的数组 a 和一个整数 size,请你编写一个函数, void print(int a[], int size), 打印数组 a 中的前 size 个数。
输入格式
第一行包含两个整数 n 和 size。
第二行包含 n 个整数 a[i],表示整个数组。
输出格式
共一行,包含 size 个整数,表示数组的前 size 个数。
数据范围
1≤n≤1000,
1≤size≤n,
输入样例:
5 3
1 2 3 4 5
输出样例:
1 2 3
#include2.6 打印矩阵using namespace std; void print(int a[], int size) { for(int i = 0; i < size; i ++) { cout << a[i] << " "; } } int main() { int n, size; cin >> n >> size; int a[n]; for(int i = 0; i < n; i ++) cin >> a[i]; print(a, size); return 0; }
给定一个 row×col 的二维数组 a,请你编写一个函数,void print2D(int a[][N], int row, int col),打印数组构成的 row 行,col 列的矩阵。
注意,每打印完一整行需要输出一个回车。
输入格式
第一行包含两个整数 row,col。
接下来 row 行,每行包含 col 个整数,表示完整二维数组 a。
输出格式
共 row 行,每行 col 个整数,表示打印出的矩阵。
数据范围
1≤row≤100,
1≤col≤100
输入样例:
3 4
1 3 4 5
2 6 9 4
1 4 7 5
输出样例:
1 3 4 5
2 6 9 4
1 4 7 5
#include2.7 递归求阶乘using namespace std; int a[100][100]; void print2D(int a[][100], int row, int col) { for(int i = 0; i < row; i ++) { for(int j = 0; j < col; j ++) { cout << a[i][j] << " "; } cout << endl; } } int main() { int row, col; cin >> row >> col; for(int i = 0; i < row; i ++) { for(int j = 0; j < col; j ++) { cin >> a[i][j]; } } print2D(a, row, col); return 0; }
请使用递归的方式求 n 的阶乘。
输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数,表示 n 的阶乘的值。
数据范围
1≤n≤10
输入样例:
3
输出样例:
6
#include2.8 递归求斐波那契数列using namespace std; int fact(int n) { if(n == 1) return 1; else return n * fact(n - 1); } int main() { int n; cin >> n; cout << fact(n) << endl; return 0; }
请使用递归的方式求斐波那契数列的第 n 项。
斐波那契数列:1,1,2,3,5…,这个数列从第 3 项开始,每一项都等于前两项之和
输入格式
共一行,包含整数 n。
输出格式
共一行,包含一个整数,表示斐波那契数列的第 n 项。
数据范围
1≤n≤30
输入样例:
4
输出样例:
3
//这是循环的写法 #includeusing namespace std; int a[30]; int cal(int a[]) { for(int i = 0; i < 30; i ++) { if(i == 0 || i == 1) a[i] = 1; else a[i] = a[i - 1] + a[i - 2]; } return 0; } int main() { int n; cin >> n; cal(a); cout << a[n - 1] << endl; return 0; }
//这是用递归的方式写出来的 #includeusing namespace std; int a[30]; int cal(int n) { if(n == 1 || n == 2) return 1; else return (cal(n - 1) + cal(n - 2)); } int main() { int n; cin >> n; cout << cal(n) << endl; return 0; }
递归的图示,类似于树的深度优先遍历,可以从图中看出f(2)和f(1)重复算很多次,效率比较低。
输入一个整数 x,请你编写一个函数,int abs(int x),输出 x 的绝对值。
输入格式
共一行,包含一个整数 x。
输出格式
共一行,包含 x 的绝对值。
数据范围
−100≤x≤100
输入样例:
-3
输出样例:
3
#include2.10 两个数的和using namespace std; int abs(int x) { if(x < 0) return -x; return x; } int main() { int x; cin >> x; cout << abs(x) << endl; return 0; }
输入两个浮点数 x 和 y,请你编写一个函数,double add(double x, double y),计算并输出 x 与 y 的和。
输入格式
共一行,包含两个浮点数 x 和 y。
输出格式
共一行,包含一个浮点数,表示两个数的和,结果保留 2 位小数。
数据范围
−1000≤x,y≤1000
输入样例:
1.11 2.22
输出样例:
3.33
#include2.11 区间求和using namespace std; double add(double x, double y) { return x + y; } int main() { double x, y; cin >> x >> y; printf("%.2lf", add(x, y)); return 0; }
输入两个整数 l 和 r,请你编写一个函数,int sum(int l, int r),计算并输出区间 [l,r] 内所有整数的和。
输入格式
共一行,包含两个整数 l 和 r。
输出格式
共一行,包含一个整数,表示所求的和。
数据范围
1≤l≤r≤1000
输入样例:
3 5
输出样例:
12
#include2.12 最小公倍数using namespace std; int sum(int l, int r) { return (l + r) * (r - l + 1) / 2; } int main() { int l, r; cin >> l >> r; cout << sum(l, r) << endl; return 0; }
输入两个整数 a 和 b,请你编写一个函数,int lcm(int a, int b),计算并输出 a 和 b 的最小公倍数。
输入格式
共一行,包含两个整数 a 和 b。
输出格式
共一行,包含一个整数,表示 a 和 b 的最小公倍数。
数据范围
1≤a,b≤1000
输入样例:
6 8
输出样例:
24
#include2.13 复制数组using namespace std; int lcm(int a, int b) { for(int i = 1; i <= a * b; i ++) { if(i % a == 0 && i % b == 0) return i; } } int main() { int a, b; cin >> a >> b; cout << lcm(a, b) << endl; return 0; }
给定两个数组 a 和 b 以及一个整数 size,请你编写一个函数,void copy(int a[], int b[], int size),将 a 数组中的前 size 个数字,复制到 b 数组中。
复制完成后,输出 b 数组。
输入格式
第一行包含整数 n,m,size,分别表示 a 数组的长度,b 数组的长度以及整数 size。
第二行包含 n 个整数,表示数组 a。
第三行包含 m 个整数,表示数组 b。
输出格式
共一行,包含 m 个整数,表示复制完成后的数组 b。
数据范围
1≤n≤m≤100,
1≤size≤n
输入样例:
3 5 2
1 2 3
4 5 6 7 8
//手动实现 #includeusing namespace std; int a[100], b[100]; void input(int n, int m) { for(int i = 0; i < n; i ++) cin >> a[i]; for(int i = 0; i < m; i ++) cin >> b[i]; } void copy(int a[], int b[], int size) { for(int i = 0; i < size; i ++) { b[i] = a[i]; } } void output(int m) { for(int i = 0; i < m; i ++) cout << b[i] << " "; } int main() { int n, m, size; cin >> n >> m >> size; input(n, m); copy(a, b, size); output(m); return 0; }
//方法二:memcpy函数的实现 #include2.14 打印字符串#include using namespace std; int a[100], b[100]; void input(int n, int m) { for(int i = 0; i < n; i ++) cin >> a[i]; for(int i = 0; i < m; i ++) cin >> b[i]; } void copy(int a[], int b[], int size) { memcpy(b, a, size * 4); } void output(int m) { for(int i = 0; i < m; i ++) cout << b[i] << " "; } int main() { int n, m, size; cin >> n >> m >> size; input(n, m); copy(a, b, size); output(m); return 0; }
给定一个字符串,请你编写一个函数,void print(char str[]),将这个字符串打印出来。
输入格式
共一行,包含一个字符串。
输出格式
共一行,表示打印出的字符串。
数据范围
1≤字符串长度≤100
输入样例:
I love AcWing.
输出样例:
I love AcWing.
#include2.15 数组翻转using namespace std; char a[110]; void print(char str[]) { puts(str); } int main() { //fgets函数容易多读入一个回车 cin.getline(a, 110); print(a); return 0; }
给定一个长度为 n 的数组 a 和一个整数 size,请你编写一个函数,void reverse(int a[], int size),实现将数组 a 中的前 size 个数翻转。
输出翻转后的数组 a。
输入格式
第一行包含两个整数 n 和 size。
第二行包含 n 个整数,表示数组 a。
输出格式
共一行,包含 n 个整数,表示翻转后的数组 a。
数据范围
1≤size≤n≤1000,
1≤a[i]≤1000
输入样例:
5 3
1 2 3 4 5
输出样例:
3 2 1 4 5
#includeusing namespace std; const int N = 1010; int a[N]; void reverse(int a[], int size) { for(int i = 0; a[i]; i ++) { if(i >= size) cout << a[i] << " "; else cout << a[size - (i + 1)] << " "; } } int main() { int n, size; cin >> n >> size; for(int i = 0; i < n; i ++) cin >> a[i]; reverse(a, size); return 0; }
//一种思路比较巧的做法 #include2.16 数组去重using namespace std; const int N = 1010; int a[N]; void reverse(int a[], int size) { for(int i = 0, j = size - 1; i < j; i ++, j --) swap(a[i], a[j]); } int main() { int n, size; cin >> n >> size; for(int i = 0; i < n; i ++) cin >> a[i]; reverse(a, size); for(int i = 0; i < n; i ++) cout << a[i] << " "; return 0; }
给定一个长度为 n 的数组 a,请你编写一个函数:
int get_unique_count(int a[], int n); // 返回数组前n个数中的不同数的个数
输入格式
第一行包含一个整数 n。
第二行包含 n 个整数,表示数组 a。
输出格式
共一行,包含一个整数表示数组中不同数的个数。
数据范围
1≤n≤1000,
1≤ai≤1000。
输入样例:
5
1 1 2 4 5
输出样例:
4
注意:本题的重复数字计算方法是把数组分成两部分,前n个数和剩下的数。计算前n个数重复的数加上剩下的数(剩下的数不统计重复)。不是整个数组计算重复的数。
#include2.17 数组排序using namespace std; const int N = 1000; int a[N]; int get_unique_count(int a[], int n) { int sum = 0; for(int i = 0; a[i]; i ++) sum ++; int tmp = 0; for(int i = 0; i < n; i ++) { for(int j = 0; j < i; j ++) { if(a[i] == a[j]) { tmp ++; break; } } } return sum - tmp; } int main() { int n; cin >> n; int k = 0; while(cin >> a[k]) k ++; cout << get_unique_count(a, n) << endl; return 0; }
给定一个长度为 n 的数组 a 以及两个整数 l 和 r,请你编写一个函数,void sort(int a[], int l, int r),将 a[l]∼a[r] 从小到大排序。
输出排好序的数组 a。
输入格式
第一行包含三个整数 n,l,r。
第二行包含 n 个整数,表示数组 a。
输出格式
共一行,包含 n 个整数,表示排序完成后的数组 a。
数据范围
0≤l≤r
5 2 4
4 5 1 3 2
输出样例:
4 5 1 2 3
//冒泡排序 #include2.18 跳台阶#include using namespace std; void sort(int a[], int l, int r) { for(int i = l; i <= r; i ++) { for(int j = i + 1; j <= r; j ++) { if(a[j] < a[i]) swap(a[j], a[i]); } } } int main() { int n, l, r; cin >> n >> l >> r; int a[n]; for(int i = 0; i < n; i ++) cin >> a[i]; sort(a, l, r); for(auto c: a) cout << c << " "; return 0; }
一个楼梯共有 n 级台阶,每次可以走一级或者两级,问从第 0 级台阶走到第 n 级台阶一共有多少种方案。
输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数,表示方案数。
数据范围
1≤n≤15
输入样例:
5
输出样例:
8
//按递归函数写 #includeusing namespace std; int func(int n) { if(n == 1 || n == 0) return 1; else return (func(n - 1) + func(n - 2)); } int main() { int n; cin >> n; cout << func(n) << endl; return 0; }
//按递归搜索树的搜索顺序写 #includeusing namespace std; int n; int ans; void f(int k) { if(k == n) ans ++; else if(k < n) { f(k + 1); f(k + 2); } } int main() { cin >> n; f(0); cout << ans << endl; return 0; }
递归函数的做法高度数学抽象化总结出规律(斐波那契),递归搜索树像是模拟了一遍所有的 2.19 走方格
给定一个 n×m 的方格阵,沿着方格的边线走,从左上角 (0,0) 开始,每次只能往右或者往下走一个单位距离,问走到右下角 (n,m) 一共有多少种不同的走法。
输入格式
共一行,包含两个整数 n 和 m。
输出格式
共一行,包含一个整数,表示走法数量。
数据范围
1≤n,m≤10
输入样例:
2 3
输出样例:
10
#include2.20 排列using namespace std; int n, m; int ans = 0; void f(int x, int y) { if(x == n && y == m ) ans ++; else if(x == n && y != m) f(x, y + 1); else if(x != n && y == m) f(x + 1, y); else { f(x + 1, y); f(x, y + 1); } } int main() { cin >> n >> m; f(0, 0); cout << ans << endl; return 0; }
给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出。
输入格式
共一行,包含一个整数 n。
输出格式
按字典序输出所有排列方案,每个方案占一行。
数据范围
1≤n≤9
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
#include#include using namespace std; const int N = 10; int n; void dfs(int k, int nums[], bool st[]) { if(k > n) { //1.为什么要从1开始,题目从1到9,数组填数的时候就不能填0,最小填1进去,所以数组是从1开始遍历的 //2.遇到输出比较多的程序使用scanf和printf比较快 for(int i = 1; i <= n; i ++) printf("%d ", nums[i]); puts(""); } else { for(int i = 1; i <= n; i ++) { if(!st[i]) { st[i] = true; nums[k] = i; dfs(k + 1, nums, st); st[i] = false;//恢复现场 } } } } int main() { scanf("%d", &n); int nums[N]; bool st[N] = {0}; dfs(1, nums, st); return 0; }



