rust学习笔记12-hashmap与1. 两数之和

rust集合中也有hashmap,昨天已经提到过,学过java同学再熟悉不过了,一道经典面试题问hashmap在java1.8的实现原理,数组+哈希表+红黑树,rust中hashmap在功能上和java一样,但实现上有很大差别,它的基本用法如下

复制代码
use std::collections::HashMap;

let mut map: HashMap<&str, i32> = HashMap::new();

// 插入键值对
map.insert("Alice", 25);
map.insert("Bob", 30);

// 查找键值
match map.get("Alice") {
    Some(&age) => println!("Alice 的年龄是: {}", age),
    None => println!("未找到 Alice"),
};

// 遍历哈希表
for (key, value) in &map {
    println!("{}: {}", key, value);
}

rust和java1.8中hashmap,相同和不同点我整理了一下:

相同点

基本功能:

两者都用于存储键值对,并且通过键来快速查找对应的值。

都基于哈希表实现,平均时间复杂度为 O(1)。

支持的操作:

插入(put/insert)、删除(remove)、查找(get)等操作。

提供遍历方法,可以访问所有的键值对。

哈希冲突处理:

两者都使用哈希函数将键映射到桶中,并处理哈希冲突(例如链地址法或开放寻址法)。

泛型支持:

两者都支持泛型类型参数,允许指定键和值的类型。

区别

特性 Rust 的 HashMap Java 1.8 的 HashMap
冲突处理 拉链法(链表) 链表 + 红黑树(长度 ≥8 时树化)
哈希算法 默认 SipHash(安全优先) 依赖 hashCode(),优化高频类型
线程安全 需显式同步(如 Mutex 非线程安全,需用 ConcurrentHashMap
函数式操作 entry() API computeIfAbsentmerge 等 Lambda 支持
空值支持 通过 Option<T> 显式处理 允许 null 键和值
内存管理 编译时所有权检查 GC 自动回收,可能泄漏
性能重点 内存安全 + 抗 HashDoS 高冲突优化 + 并发工具

Rust 的 HashMap 更加注重安全性、性能和内存管理。它提供了严格的所有权和借用规则,确保程序在并发环境下的正确性和安全性。同时,Rust 的类型系统在编译时就进行了严格的类型检查,避免了运行时的类型错误。

Java 1.8 的 HashMap 更加注重易用性和开发效率。它提供了自动垃圾回收机制,减少了开发者手动管理内存的负担。此外,Java 的 HashMap 在并发环境下提供了 ConcurrentHashMap,简化了多线程编程的复杂性。

实战应用

1. 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

示例 1:

复制代码
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

复制代码
输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

复制代码
输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

进阶: 你可以想出一个时间复杂度小于 O(n2) 的算法吗?

解答

rust 复制代码
use std::collections::HashMap;


pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
    //设置一个map长度和数组一致
    let mut map: HashMap<i32, i32>  = HashMap::with_capacity(nums.len());

    for i in 0..nums.len() {
        //获取target - nums[i]的值,就是要寻找到值,如9-2=7, 看看map中是否存在
        let n = target - nums[i];
        if let Some(k) = map.get(&n) {
            //存在并且不等于自己本身,就找到了返回
            if *k != i as i32{
                return  vec![*k as i32, i as i32];
            }
        }
        // 不存在把数组元素和下标存放到map中
        map.insert(nums[i], i as i32);

    }
    return  vec![];
        
}

fn main() {
    let res = two_sum(vec![2,7,3,6], 9);
    println!("{:?}", res);
}

match模式匹配版本

rust 复制代码
use std::collections::HashMap;

pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
    //设置一个map长度和数组一致
    let mut map: HashMap<i32, i32>  = HashMap::with_capacity(nums.len());

    for i in 0..nums.len() {
        //获取target - nums[i]的值,就是要寻找到值,如9-2=7, 看看map中是否存在
        let n = target - nums[i];
        // 查找键值
        match map.get(&n) {
            Some(&k) => {
                if k != i as i32{
                    return vec![k , i as i32];
                }
            }
            None => {
                // 不存在把数组元素和下标存放到map中
                map.insert(nums[i], i as i32);
            }
        };

    }
    return  vec![];
        
}



fn main() {
    let res = two_sum(vec![2,7,3,6], 9);
    println!("{:?}", res);
}

总结rust使用HashMap判断key是否存在用的是引用类型&n,获取数值是*k,这点需要注意,如果不愿意使用*k,可以在Some(&k)也使用引用类型,这样就可以不用加*了。

相关推荐
WDeLiang8 分钟前
学习笔记 - Swfit 6.1 - 语法概览
笔记·学习·swift
手揽回忆怎么睡29 分钟前
mongodb学习
数据库·学习·mongodb
arriettyandray36 分钟前
Qt/C++学习系列之QTreeWidget的简单使用记录
c++·qt·学习
LL1681991 小时前
SSM考研助手管理系统
java·服务器·开发语言·数据库·学习
红白小蛋糕1 小时前
《操作系统真象还原》第八章(1)——内存管理系统
汇编·笔记·ubuntu
凡人的AI工具箱2 小时前
PyTorch深度学习框架60天进阶学习计划 - 第41天:生成对抗网络进阶(一)
人工智能·pytorch·python·深度学习·学习·生成对抗网络
zhaoyqcsdn2 小时前
C++对象池设计:从高频`new/delete`到性能飞跃的工业级解决方案
c++·经验分享·笔记
苏卫苏卫苏卫2 小时前
【Vue】案例——To do list:
开发语言·前端·javascript·vue.js·笔记·list
大雄野比2 小时前
【scikit-learn基础】--『监督学习』之 K-近邻分类
学习·分类·scikit-learn
0509152 小时前
测试基础笔记第四天(html)
前端·笔记·html