Rust每日一练(Leetday0004) 正则表达、盛水容器、转罗马数字

简介: Rust每日一练(Leetday0004) 正则表达、盛水容器、转罗马数字

10. 正则表达式匹配 Regular Expression Matching


给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.''*' 的正则表达式匹配。


  • '.' 匹配任意单个字符
  • '*' 匹配零个或多个前面的那一个元素



所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

示例 1:

输入:s = "aa", p = "a"

输出:false

解释:"a" 无法匹配 "aa" 整个字符串。


示例 2:

输入:s = "aa", p = "a*"

输出:true

解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。


示例 3:

输入:s = "ab", p = ".*"

输出:true

解释:".*" 表示可匹配零个或多个('*')任意字符('.')。


提示:

   1 <= s.length <= 20

   1 <= p.length <= 30

   s 只包含从 a-z 的小写字母。

   p 只包含从 a-z 的小写字母,以及字符 . 和 *。

   保证每次出现字符 * 时,前面都匹配到有效的字符


代码:


fn is_match(s: &str, p: &str) -> bool {
    let s_len = s.len();
    let p_len = p.len();
    let mut dp = vec![vec![false; p_len + 1]; s_len + 1];
    dp[0][0] = true;
    for i in 0..=s_len {
        for j in 1..=p_len {
            if p.chars().nth(j - 1).unwrap() == '*' {
                dp[i][j] = dp[i][j - 2];
                if match_str(s, p, i, j - 1) {
                    dp[i][j] = dp[i][j] || dp[i - 1][j];
                }
            } else {
                if match_str(s, p, i, j) {
                    dp[i][j] = dp[i - 1][j - 1];
                }
            }
        }
    }
    dp[s_len][p_len]
}
fn match_str(s: &str, p: &str, i: usize, j: usize) -> bool {
    if i == 0 {
        false
    } else if p.chars().nth(j - 1).unwrap() == '.' {
        true
    } else {
        s.chars().nth(i - 1).unwrap() == p.chars().nth(j - 1).unwrap()
    }
}
fn main() {
    println!("{}", is_match("aa", "a"));
    println!("{}", is_match("aa", "a*"));
    println!("{}", is_match("ab", ".*"));
}


输出:

false

true

true

说明:

动态规划,定义一个二维数组dp,dp[i][j]表示s的前i个字符和p的前j个字符是否匹配。



11. 盛最多水的容器 Container with most water


给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])



找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。


示例 1:

d819aa36d103701174372cb3996c1b72.jpeg


输入:[1,8,6,2,5,4,8,3,7]

输出:49  

解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。


示例 2:

输入:height = [1,1]

输出:1


提示:

   n == height.length

   2 <= n <= 10^5

   0 <= height[i] <= 10^4

代码:


fn max_area(height: Vec<i32>) -> i32 {
    let mut max = 0;
    let mut start = 0;
    let mut end = height.len() - 1;
    while start < end {
        let width = end - start;
        let curr = if height[start] < height[end] {
            height[start]
        } else {
            height[end]
        };
        let temp = width as i32 * curr;
        if temp > max {
            max = temp;
        }
        if height[start] < height[end] {
            start += 1;
        } else {
            end -= 1;
        }
    }
    max
}
fn main() {
    println!("{}", max_area(vec![1, 8, 6, 2, 5, 4, 8, 3, 7]));
    println!("{}", max_area(vec![1, 1]));
}


输出:

49

1

说明:

双指针,定义两个指针 start 和 end,分别指向数组的头和尾。初始时,它们之间的距离就是数组的长度。然后,以较小的高度为准,计算两个指针围成的面积,并更新最大面积。接着,将较小高度的指针向中间移动。





12. 整数转罗马数字 Integer to Roman


罗马数字包含以下七种字符: IVXLCDM



字符          数值

I             1

V             5

X             10

L             50

C             100

D             500

M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:


   I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。

   X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。  

   C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。


给你一个整数,将其转为罗马数字。


示例 1:

输入: num = 3

输出: "III"


示例 2:

输入: num = 4

输出: "IV"


示例 3:

输入: num = 9

输出: "IX"


示例 4:

输入: num = 58

输出: "LVIII"

解释: L = 50, V = 5, III = 3.


示例 5:

输入: num = 1994

输出: "MCMXCIV"

解释: M = 1000, CM = 900, XC = 90, IV = 4.


提示:

   1 <= num <= 3999

代码:

fn int_to_roman(mut num: i32) -> String {
    let values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
    let symbols = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"];
    let mut roman = String::new();
    for i in 0..values.len() {
        while values[i] <= num {
            num -= values[i];
            roman += symbols[i];
        }
    }
    roman
}
fn main() {
    println!("{}", int_to_roman(9));
    println!("{}", int_to_roman(58));
    println!("{}", int_to_roman(1994));
}


输出:

IX

LVIII

MCMXCIV


目录
相关文章
|
4月前
|
算法 容器
【LeetCode刷题】快乐数、盛水最多的容器
【LeetCode刷题】快乐数、盛水最多的容器
|
5月前
|
算法 容器
每日一题:LeetCode-11.盛水最多的容器
每日一题:LeetCode-11.盛水最多的容器
|
5月前
|
Java Go C++
Rust每日一练(Leetday0031) 解码方法、复原 IP 地址
Rust每日一练(Leetday0031) 解码方法、复原 IP 地址
58 0
Rust每日一练(Leetday0031) 解码方法、复原 IP 地址
|
5月前
|
Java Go Rust
Rust每日一练(Leetday0030) 合并有序数组、格雷编码、子集II
Rust每日一练(Leetday0030) 合并有序数组、格雷编码、子集II
73 0
Rust每日一练(Leetday0030) 合并有序数组、格雷编码、子集II
|
5月前
|
算法 Java Go
Rust每日一练(Leetday0029) 柱状图、最大矩形、扰乱字符串
Rust每日一练(Leetday0029) 柱状图、最大矩形、扰乱字符串
48 0
Rust每日一练(Leetday0029) 柱状图、最大矩形、扰乱字符串
|
5月前
|
Rust Java Go
Rust每日一练(Leetday0027) 单词搜索、删除重复项II、搜索旋转排序数组II
Rust每日一练(Leetday0027) 单词搜索、删除重复项II、搜索旋转排序数组II
54 0
Rust每日一练(Leetday0027) 单词搜索、删除重复项II、搜索旋转排序数组II
|
5月前
|
Java Go C++
Rust每日一练(Leetday0026) 最小覆盖子串、组合、子集
Rust每日一练(Leetday0026) 最小覆盖子串、组合、子集
57 0
Rust每日一练(Leetday0026) 最小覆盖子串、组合、子集
|
5月前
|
Java 容器
LeetCode题解-盛水最多的容器-Java
盛水最多的容器-Java
23 0
|
14天前
|
Linux iOS开发 Docker
Docker:容器化技术的领航者 —— 从基础到实践的全面解析
在云计算与微服务架构日益盛行的今天,Docker作为容器化技术的佼佼者,正引领着一场软件开发与部署的革命。它不仅极大地提升了应用部署的灵活性与效率,还为持续集成/持续部署(CI/CD)提供了强有力的支撑。
192 69
|
2天前
|
Kubernetes Cloud Native 持续交付
云原生之旅:Docker容器化与Kubernetes集群管理
【9月更文挑战第33天】在数字化转型的浪潮中,云原生技术如同一艘航船,带领企业乘风破浪。本篇文章将作为你的航海指南,从Docker容器化的基础讲起,直至Kubernetes集群的高级管理,我们将一起探索云原生的奥秘。你将学习到如何封装应用、实现环境隔离,以及如何在Kubernetes集群中部署、监控和扩展你的服务。让我们启航,驶向灵活、可伸缩的云原生未来。
下一篇
无影云桌面