编程学习

编程学习

博客里已经有Rust学习了,但那个准备更一些从零开始学习的东西

这篇博客就记录一下我在刷牛客和leetcode时,发现的一些小知识吧,因为不限语言,所以叫做编程学习

1.牛客 CPP11判断季节

题目:CPP11判断季节

这里我首先想到的解法是使用 if - else 判断结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
 
int main() {
     
    int month;
    cin >> month;
 
    if (month == 3 || month == 4 || month == 5) {
        cout << "春季";
    } else if (month == 6 || month == 7 || month == 8) {
        cout << "夏季";
    } else if (month == 9 || month == 10 || month == 11) {
        cout << "秋季";
    } else if (month == 1 || month == 2 || month == 12) {
        cout << "冬季";
    } else {
        cout << "不合法";
    }
 
    return 0;
}

但总感觉这样实现不太优雅,看题解发现有人使用switch 判断结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <ostream>
using namespace std;

int main() {
    
    int month;
    cin >> month;

    switch (month) {
        case 1:
        case 2:
        case 12:
            cout << "冬季" << endl;
            break;
        case 3:
        case 4:
        case 5:
            cout << "春季" << endl;
            break;
        case 6:
        case 7:
        case 8:
            cout << "夏季" << endl;
            break;
        case 9:
        case 10:
        case 11:
            cout << "秋季" << endl;
            break;
        default:
            cout << "不合法" << endl;
    }

    return 0;
}

但是这样写得还是有点不太优雅

最后看最高赞题解是这样,同样是switch 判断

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;
 
int main() {
     
    int month;
    cin >> month;
    if(month < 1 || month > 12) //优先判断是否合法月份
        cout << "不合法" << endl;
    else{
        switch(month){ //根据月份判断
            case 3 ... 5: //连续的值
                cout << "春季" << endl;  break;
            case 6 ... 8:
                cout << "夏季" << endl;  break;
            case 9 ... 11:
                cout << "秋季" << endl;  break;
            default:
                cout << "冬季" << endl;
        }
    }
    return 0;
}

这样写的原因是,首先为了避免使用麻烦的 if - else ,选择使用switch , 而且因为是判断季节,月份的值大多是连续的,所以可以使用case的连续写法:在case中,可以用x…y表示范围在 [x,y] 的值,两边都是闭区间。

所以在代码中 case3: case4: case5: 就变成了 case 3...5: 最后冬季不连续,就使用 default 代替,由于已经使用 if 将月份值限制在 1 - 12范围内,除去以上三种情况就剩冬季了

2.牛客 CPP12 求 1~n之间偶数的和

题目: CPP12 求 1~n之间偶数的和

好久没写了连while的用法都忘了,按理说以前这个同样在牛客上用rust写过,应该是不能忘的QAQ

while 循环和 for 循环本质是同一种循环的两种不同形式

while 循环事先只设定好了循环的终点,在此范围内不断执行语句,具体其他的限制条件在循环内部定义

for 循环则事先设定好了循环的终点,以及循环的规则(如 i++ 设定在循环外)

因此while循环要比 for 循环稍微灵活一些

在Rust 中,在程序编译时,编译器会把 while 去糖化变成 “一个无限循环 + 一个条件判断和 break” ,类似于这样:

1
2
3
4
5
let mut i = 0;
while i < 10 {
    println!("{}", i);
    i += 1;
}

在 MIR 层面,它会被转换成类似下面这样的逻辑:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let mut i = 0;
loop {
    if i < 10 {
        // 循环体
        println!("{}", i);
        i += 1;
    } else {
        break; // 条件不满足,退出循环
    }
}

同样的,编译器也会对 for 循环做相似的去糖化处理:

去糖化过程:for -> while let -> loop

Rust 中的 for 循环之所以强大和灵活,是因为它本质上是在遍历一个迭代器(Iterator),因此,任何一个 for 循环都会被编译器转换成一个使用 while let 和迭代器的等价结构

  1. 牛客 CPP13 计算一个数的阶乘

CPP13 计算一个数的阶乘

最适合区分递归和迭代的题目,但我只想到了迭代的实现,忘记递归是怎么实现的了

迭代:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

int main() {
    
    int n;
    cin >> n;
    long long factorial = 1;
    
    for (int i = 2; i <= n; i++) {
        factorial *= i;
    }
    

    cout << factorial << endl;
    
    return 0;
}

递归:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;

long long fac(int n) {
    if (n == 1) {
        return 1;
    }

    return fac(n-1) * n;
}

int main() {
    
    int n;
    cin >> n;
    long long factorial = fac(n);

    cout << factorial << endl;
    
    return 0;
}

这里遇见了一个小小的问题,C++中函数声明必须在调用前,但Rust就不需要

这里写一下相同的问题使用Rust是如何解决的:

迭代:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
use std::io;

fn main() {
    let mut stdin = String::new();

    io::stdin().read_line(&mut stdin).expect("");

    let n = stdin
        .trim()
        .parse()
        .expect("");

    let mut x = 1;
    for i in 2..=n {
        x *= i;
    }

    println!("{}", x);
}

递归:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
use std::io;

fn main() {
    let mut stdin = String::new();

    io::stdin().read_line(&mut stdin).expect("");

    let n = stdin
        .trim()
        .parse()
        .expect("");

    let x = factorial(n);

    println!("{}", x);
}

fn factorial(n: i64) -> i64 {
    if n == 1 {
        return 1;
    }

    return n * factorial(n - 1);
}
Licensed under CC BY-NC-SA 4.0
Build by Oight
使用 Hugo 构建
主题 StackJimmy 设计