第六章 函数

目录

  • 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.函数在传二维数组的时候,列数一定要写。因为二维数组在存储的时候是连续的一段空间,数组名相当于行指针(行信息),如果不告诉计算机列数(列信息),那和一维数组没有什么区别。如果告诉了,计算机就会知道面对一段连续的数组怎么划分行和列。

2.练习题

2.1 n的阶乘

输入一个整数 n,请你编写一个函数,int fact(int n),计算并输出 n 的阶乘。

输入格式
共一行,包含一个整数 n。

输出格式
共一行,包含一个整数表示 n 的阶乘的值。

数据范围
1≤n≤10
输入样例:
3
输出样例:
6

#include 
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;
}

2.2 x和y的最大值

输入两个整数 x 和 y,请你编写一个函数,int max(int x, int y),计算并输出 x 和 y 的最大值。

输入格式
共一行,包含两个整数 x 和 y。

输出格式
共一行,包含一个整数,表示两个数中较大的那个数。

数据范围
−100≤x,y≤100
输入样例:
3 6
输出样例:
6

#include 
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;
}

2.3 最大公约数

输入两个整数 a 和 b,请你编写一个函数,int gcd(int a, int b), 计算并输出 a 和 b 的最大公约数。

输入格式
共一行,包含两个整数 a 和 b。

输出格式
共一行,包含一个整数,表示 a 和 b 的最大公约数。

数据范围
1≤a,b≤1000
输入样例:
12 16
输出样例:
4

//求最大公约数有个简便的方法,叫转展相除法
#include 
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;
    }
}

2.4 交换数值

输入两个整数 x 和 y,请你编写一个函数,void swap(int &x, int &y), 交换两个整数的数值并输出交换后的 x 和 y。

输入格式
共一行,包含两个整数 x 和 y。

输出格式
共一行,包含交换后的 x 和 y。

数据范围
1≤x,y≤100
输入样例:
3 5
输出样例:
5 3

#include 
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;
}

2.5 打印数字

输入一个长度为 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

#include 
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;
}

2.6 打印矩阵

给定一个 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

#include 
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;
}

2.7 递归求阶乘

请使用递归的方式求 n 的阶乘。

输入格式
共一行,包含一个整数 n。

输出格式
共一行,包含一个整数,表示 n 的阶乘的值。

数据范围
1≤n≤10
输入样例:
3
输出样例:
6

#include 
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;
}

2.8 递归求斐波那契数列

请使用递归的方式求斐波那契数列的第 n 项。

斐波那契数列:1,1,2,3,5…,这个数列从第 3 项开始,每一项都等于前两项之和

输入格式
共一行,包含整数 n。

输出格式
共一行,包含一个整数,表示斐波那契数列的第 n 项。

数据范围
1≤n≤30
输入样例:
4
输出样例:
3

//这是循环的写法
#include 
using 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;
}
//这是用递归的方式写出来的
#include 
using 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;
}

第六章 函数_第1张图片
递归的图示,类似于树的深度优先遍历,可以从图中看出f(2)和f(1)重复算很多次,效率比较低。

2.9 绝对值

输入一个整数 x,请你编写一个函数,int abs(int x),输出 x 的绝对值。

输入格式
共一行,包含一个整数 x。

输出格式
共一行,包含 x 的绝对值。

数据范围
−100≤x≤100
输入样例:
-3
输出样例:
3

#include 
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;
}

2.10 两个数的和

输入两个浮点数 x 和 y,请你编写一个函数,double add(double x, double y),计算并输出 x 与 y 的和。

输入格式
共一行,包含两个浮点数 x 和 y。

输出格式
共一行,包含一个浮点数,表示两个数的和,结果保留 2 位小数。

数据范围
−1000≤x,y≤1000
输入样例:
1.11 2.22
输出样例:
3.33

#include 
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;
}

2.11 区间求和

输入两个整数 l 和 r,请你编写一个函数,int sum(int l, int r),计算并输出区间 [l,r] 内所有整数的和。

输入格式
共一行,包含两个整数 l 和 r。

输出格式
共一行,包含一个整数,表示所求的和。

数据范围
1≤l≤r≤1000
输入样例:
3 5
输出样例:
12

#include 
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;
}

2.12 最小公倍数

输入两个整数 a 和 b,请你编写一个函数,int lcm(int a, int b),计算并输出 a 和 b 的最小公倍数。

输入格式
共一行,包含两个整数 a 和 b。

输出格式
共一行,包含一个整数,表示 a 和 b 的最小公倍数。

数据范围
1≤a,b≤1000
输入样例:
6 8
输出样例:
24

#include 
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;
}

2.13 复制数组

给定两个数组 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

//手动实现
#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)
{
    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函数的实现
#include 
#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;
}

2.14 打印字符串

给定一个字符串,请你编写一个函数,void print(char str[]),将这个字符串打印出来。

输入格式
共一行,包含一个字符串。

输出格式
共一行,表示打印出的字符串。

数据范围
1≤字符串长度≤100
输入样例:
I love AcWing.
输出样例:
I love AcWing.

#include 
using namespace std;

char a[110];

void print(char str[])
{
    puts(str);
}
int main()
{
//fgets函数容易多读入一个回车
    cin.getline(a, 110);
    print(a);
    return 0;
}

2.15 数组翻转

给定一个长度为 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

#include 
using 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;
}
//一种思路比较巧的做法
#include 
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;
}

2.16 数组去重

给定一个长度为 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个数重复的数加上剩下的数(剩下的数不统计重复)。不是整个数组计算重复的数。
#include 
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;
}

2.17 数组排序

给定一个长度为 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

//冒泡排序
#include 
#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;                                              
}

2.18 跳台阶

一个楼梯共有 n 级台阶,每次可以走一级或者两级,问从第 0 级台阶走到第 n 级台阶一共有多少种方案。

输入格式
共一行,包含一个整数 n。

输出格式
共一行,包含一个整数,表示方案数。

数据范围
1≤n≤15
输入样例:
5
输出样例:
8

//按递归函数写
#include 
using 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;
}

第六章 函数_第2张图片

//按递归搜索树的搜索顺序写
#include 
using 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

#include 
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;
}

2.20 排列

给定一个整数 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;
}

你可能感兴趣的:(C++语法基础练习题,c/c++,算法,c++,c语言)