1. 两数之和
/**
* 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返 * 回他们的数组下标。
* 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
* 示例:
* 给定 nums = [2, 7, 11, 15], target = 9
* 因为 nums[0] + nums[1] = 2 + 7 = 9
* 所以返回 [0, 1]
*/
use std::collections::HashMap;
pub struct Solution {}
impl Solution {
pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
let mut map = HashMap::with_capacity(nums.len());
for (index, num) in nums.iter().enumerate() {
println!("index:{} num:{}", index, num);
match map.get(&(target - num)) {
None => {
map.insert(num, index);
}
Some(sub_index) => return vec![*sub_index as i32, index as i32],
}
}
vec![]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_0001_1() {
assert_eq!(vec![0, 1], Solution::two_sum(vec![2, 7, 11, 15], 9));
}
#[test]
fn test_0001_2() {
assert_eq!(vec![1, 3], Solution::two_sum(vec![2, 5, 8, 9, 13], 14));
}
#[test]
fn test_0001_3() {
assert_eq!(vec![0, 2], Solution::two_sum(vec![3, 2, 4], 6));
}
}
知识拾遗
https://doc.rust-lang.org/std/collections/struct.HashMap.html
哈希表(HashMap)是Rust内置的集合类型之一,属于std::collections模块下,它提供了一个平均复杂度为O(1)的查询方法。HashMap 的键可以是布尔型、整型、字符串,或任意实现了 Eq 和 Hash trait 的其他类型(要求所有的键必须是相同类型)和一个编译时知道大小的Value类型,值也必须都是相同类型。 同时,Rust还要求你的Key类型必须是可比较的。HashMap 也是可增长的,但 HashMap 在空间多余时能够缩小自身。
- 创建 HashMap,可以使用适当的初始化容器(starting capacity) HashMap::with_capacity(unit),或者使用 HashMap::new() 来获得一个带有默认初始容器的 HashMap(推荐方式)。
- HashMap的数据是存储在堆上。在Rust中,你可以为你的类型轻易的加上编译器属性:
#[derive(PartialEq, Eq, Hash)]
HashMap的增删改查
use std::collections::HashMap;
fn main() {
// 声明
let mut hashmap_test = HashMap::new();
// 插入
hashmap_test.insert("key0", "value0");
hashmap_test.insert("key1", "value1");
hashmap_test.insert("key2", "value2");
hashmap_test.insert("key3", "value3");
println!("{:#?}", hashmap_test);
// 查找key
if !hashmap_test.contains_key("key5") {
println!(
"total {} keys in hashmap_test,but key5 not in it",
hashmap_test.len()
);
}
// 根据key删除元素
hashmap_test.remove("key2");
println!("after remove key2:{:#?}", hashmap_test);
// 利用get的返回判断元素是否存在
let keys = ["key0", "key4"];
for key in &keys {
match hashmap_test.get(key) {
Some(value) => println!("got key '{}' value is {}", key, value),
None => println!("{} not in hashmap_test", key),
}
}
// 遍历输出
for (key, value) in &hashmap_test {
println!("{}===>{}", key, value);
}
}
7. 整数反转
/*
* 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
* 示例 1:
* 输入: 123
* 输出: 321
*
* 示例 2:
* 输入: -123
* 输出: -321
* 示例 3:
*
* 输入: 120
* 输出: 21
* 注意:
* 假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2^31, 2^31 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
*/
pub struct Solution {}
impl Solution {
pub fn reverse(x: i32) -> i32 {
let mut newx: i64 = x as i64;
let mut result: i64 = 0;
let mut digit: i64 = 0;
while newx != 0 {
digit = newx % 10;
result = result * 10 + digit;
newx = newx / 10;
}
println!("{:?}", result);
let base: i64 = 2;
let higher: i64 = base.pow(31) - 1;
let lower: i64 = -base.pow(31);
if result < lower || result > higher {
return 0;
}
return result as i32;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_0007_1() {
assert_eq!(321, Solution::reverse(123));
}
#[test]
fn test_0007_2() {
assert_eq!(-321, Solution::reverse(-123));
}
#[test]
fn test_0007_3() {
assert_eq!(21, Solution::reverse(120));
}
}
9. 回文数
/*
* 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
*
* 示例 1:
* 输入: 121
* 输出: true
*
* 示例 2:
* 输入: -121
* 输出: false
* 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
*
* 示例 3:
* 输入: 10
* 输出: false
* 解释: 从右向左读, 为 01 。因此它不是一个回文数。
*/
pub struct Solution {}
impl Solution {
pub fn is_palindrome(x: i32) -> bool {
if (x < 0) {
return false;
}
let mut newx = x;
let mut res = 0;
while newx != 0 {
let tmp = newx % 10;
res = res * 10 + tmp;
newx = newx / 10;
}
if res == x {
return true;
} else {
return false;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_0007_1() {
assert_eq!(true, Solution::is_palindrome(212));
}
#[test]
fn test_0007_2() {
assert_eq!(false, Solution::is_palindrome(-121));
}
#[test]
fn test_0007_3() {
assert_eq!(false, Solution::is_palindrome(120));
}
#[test]
fn test_0007_4() {
assert_eq!(true, Solution::is_palindrome(0));
}
}
9. 罗马数字转整数
/*
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
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 到 3999 的范围内。
示例 1:
输入: "III"
输出: 3
示例 2:
输入: "IV"
输出: 4
示例 3:
输入: "IX"
输出: 9
示例 4:
输入: "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:
输入: "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.
*/
use std::collections::HashMap;
pub struct Solution {}
impl Solution {
pub fn roman_to_int(s: String) -> i32 {
let map: HashMap<&str, i32> = [
("I", 1),
("V", 5),
("X", 10),
("L", 50),
("C", 100),
("D", 500),
("M", 1000),
]
.iter()
.cloned()
.collect();
let mut res: i32 = map[s.get(0..1).unwrap()];
let mut i = 1usize;
println!("{:?} s len {:?}", res, s.len());
while i < s.len() {
let key0 = s.get((i - 1)..i).unwrap();
let key1 = s.get(i..(i + 1)).unwrap();
if map[key0] < map[key1] {
res = res - 2 * map[key0] + map[key1];
} else {
res += map[key1];
}
i += 1;
}
res
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_0013() {
assert_eq!(Solution::roman_to_int("III".to_string()), 3);
assert_eq!(Solution::roman_to_int("IV".to_string()), 4);
assert_eq!(Solution::roman_to_int("IX".to_string()), 9);
assert_eq!(Solution::roman_to_int("MCMXCIV".to_string()), 1994);
assert_eq!(Solution::roman_to_int("DCXXI".to_string()), 621);
}
}