rust踩雷笔记(4)——刷点Vec相关的题(持续更新)

俗话说,孰能生巧,今天是第六天接触Rust,感觉基础语法和特性没什么问题了(当然如果你整天都学这个可能2天半就够了),但是想达到熟练使用,还需要刷点题。算法我相信能来看rust博客的人都是大牛(只有我最菜),应该只有数据结构的困扰,所以接下来的博客会侧重于数据结构,毕竟咱常见算法都靠C++练得烂熟了,剩下的事情其实是做到把C++题解翻译成rust题解。

hello

      • leetcode 53 最大子数组和
      • leetcode 912——快速排序惨案
      • leetcode 743——网络延迟——Dijkstra
          • 方法一:用向量实现邻接表
            • 补充:小根堆
          • 方法二:实现邻接矩阵

leetcode 53 最大子数组和

这个毫无疑问直接用dp就行了,关键注意事项是with_capacity(n)分配的Vec,你以为它可以用数组下标访问,实际上在它真正push进数据前,下标访问会越界,哪怕dp[0]都不行。

impl Solution {pub fn max_sub_array(nums: Vec<i32>) -> i32 {let n = nums.len();println!("{n}");// 发现一个问题,即便是指定了大小,但是下面dp.len()为0,可能是因为没有元素let mut dp: Vec<i32> = Vec::with_capacity(n);   // dp[i]表示以下标i为结尾的最大连续子数组之和// println!("{}", dp.len());    // 0dp.push(nums[0]);let mut res = dp[0];for i in 1..n {// dp[i] = max(nums[i], nums[i] + dp[i - 1])let t = nums[i].max(nums[i] + dp[i - 1]);dp.push(t);res = res.max(dp[i]);}res}
}

看注释就行了,如果dp.push(nums[0])改为dp[0] = nums[0],那么会报数组下标越界。

基本的使用就是这样,我们继续看别的题

leetcode 912——快速排序惨案

为什么叫惨案,因为我直接用自己的C++解法套用过去,因为语言特性的差异而浪费了两小时。

为了你的安全,请不要嫌弃rust的特性麻烦——鲁迅

这是我C++的写法:

#include<iostream>
using namespace std;const int N = 1e6 + 10;int q[N];
void swap(int &a, int &b){int temp;temp = a;a = b;b = temp;
}void quick_sort(int q[], int l, int r){if (l >= r) return;int temp = q[(l + r) >> 1];int i = l  - 1;int j = r + 1;while(i < j){do i++; while(q[i] < temp);do j--; while(q[j] > temp);if(i < j) swap(q[i], q[j]);}quick_sort(q, l, j);quick_sort(q, j + 1, r);
}int main()
{int n;scanf("%d", &n);for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);quick_sort(q, 0, n - 1);for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);return 0;
}

看看栈溢出的rust写法,当然我还加了好多注释,全是踩到雷的地方。乍一看和C++代码一样,但是要注意usize的问题,详见注释。

impl Solution {pub fn quick_sort(a: &mut Vec<i32>, l: usize, r: usize) {// 不写递归边界会报错:thread 'main' has overflowed its stack (solution.rs)if l >= r {return ;}// 对a的下标l到r之间进行快速排序// 栈溢出的原因在这里,都是usize类型,如果l为0,那么i的值不会是-1而是很大的数// 而且只能是usize,因为需要下标访问let mut i = l - 1;let mut j = r + 1;let mid = (l + r) / 2;while i < j {// while *a[l] < *a[mid] {	// 这样是错的,a是引用但是a[i]不是,*优先级没有[]高i += 1;while a[i] < a[mid] {i += 1;}j -= 1;while a[j] > a[mid] {j -= 1;}if i < j {let temp = a[i];a[i] = a[j];a[j] = temp;}}println!("i:{}, j:{}", i, j);// 递归要加上Solution::或者Self::// Solution::quick_sort(a, l, j);// Solution::quick_sort(a, j + 1, r);Self::quick_sort(a, l, j);Self::quick_sort(a, j + 1, r);}pub fn sort_array(nums: Vec<i32>) -> Vec<i32> {// 用这行试验了一下,move occurs because `nums` has type `Vec<i32>`, which does not implement the `Copy` trait// 也就是说所有权转移给了nums1// let mut nums1 = nums;// 这句是必要的,入参那里的nums不是mutable的,所以后面&mut nums会报错。创建了新的mutable nums并将入参所有权转移过来let mut nums = nums;// 早上太困了,简单写个快速排序// 报错nums.len()这里还borrowed as immutable,不能同时是mutable和immutable的引用// Solution::quick_sort(&mut nums, 0, nums.len() - 1); let len = nums.len();Solution::quick_sort(&mut nums, 0, len - 1); nums}
}

改正之后的代码,对usize和i32进行合适的类型转换,

⚠️i32和usize不能直接相互赋值、参与运算

但是需要注意的是,let mid = (l + r) / 2 as usize;,其中l和r都是i32,你觉得这句话会报错么?
当然会!2 as usize会被当成一个整体,于是变成i32 / usize,报错。

impl Solution {pub fn quick_sort(a: &mut Vec<i32>, l: i32, r: i32) {// 不写递归边界会报错:thread 'main' has overflowed its stack (solution.rs)if l >= r {return ;}// 对a的下标l到r之间进行快速排序let mut i = l - 1;let mut j = r + 1;let mid = a[((l + r) / 2) as usize];while i < j {i += 1;while a[i as usize] < mid {i += 1;}j -= 1;while a[j as usize] > mid {j -= 1;}if i < j {let temp = a[i as usize];a[i as usize] = a[j as usize];a[j as usize] = temp;}}// Self或者Solution都可以// Solution::quick_sort(a, l, j);// Solution::quick_sort(a, j + 1, r);Self::quick_sort(a, l, j);Self::quick_sort(a, j + 1, r);}pub fn sort_array(nums: Vec<i32>) -> Vec<i32> {let mut nums = nums;let len = nums.len();Solution::quick_sort(&mut nums, 0, (len - 1) as i32); nums}
}

小结,快速排序不难,麻烦的是语言特性相关的东西:
(1)注意[]下标访问只能用usize不能用i32,下标访问比*优先级高,如果a是引用&i32,但a[i]是i32(自动“解引用”了),此时不要自作聪明用*a[i],会报错对i32没法解引用
(2)usize和i32不能相互赋值,所以xxx as usize和xxx as i32用起来,但注意优先级问题:(a + b) / 2 as usize,这是先把2转为usize
(3)Vec<i32>依旧是没有实现copy trait的,所以它的赋值会转移所有权。当然这句话和本题无关,和本题有关的是方法签名:
pub fn sort_array(nums: Vec<i32>) -> Vec<i32>,如果你要改变nums,然后返回它,由于它是immutable的,所以你需要let mut nums = nums,重新创建一个变量绑定老nums的值(当然这么做老nums的值就被move掉了),然后改变新nums并返回
(4)不要抱怨rust的特性怎么这么复杂,我一开始套用自己的解法,因为要把变量定义为i32并在若干地方加as usize,我觉得这样不优雅,就试图改变解法,结果发明了几个错误的快排写法。非常蛋疼,假如我没有嫌弃rust的写法麻烦,而是理解这是为了程序安全,就不会浪费时间了!

leetcode 743——网络延迟——Dijkstra

看下图的数据结构,无非就是邻接表和邻接矩阵,这个都可以用数组或者向量来实现。

方法一:用向量实现邻接表
补充:小根堆

注意用到了小根堆

use std::collections::BinaryHeap;
use std::cmp::Reverse;

详情见下面代码,反正push的时候如果用Reverse包起来,那就是小根堆,不包就是大根堆。
如果是小根堆,那么你heap.pop().unwrap_or(Reverse((0, 0)))查出来的是Reverse(元素),注意不是引用(加unwrap是因为pop()查出来是Some(Reverse(元素))或者None),那么需要自己解构一下。

use std::collections::BinaryHeap;
use std::cmp::Reverse;const MAX_VALUE: i32 = 100 * 100 + 7;
impl Solution {pub fn network_delay_time(times: Vec<Vec<i32>>, n: i32, k: i32) -> i32 {let (n, k) = (n as usize, k as usize);// 二维数组注意显式指定类型let mut graph = vec![vec![]; n + 1];    // graph[i]表示节点i的邻接表,注意i是1到n// 初始化图// 这道题用这里总结下遍历数组方法大全for i in 0..times.len() {// times[i] = [u,v,w],表示一条边// 二维数组除了用[][]定位元素,还有没有更好的方法// 坑死了,times是i32类型向量;坑死了+1,不要把w变成usize,后面它要和i32运算啊喂!let (u, v, w) = (times[i][0] as usize, times[i][1] as usize, times[i][2]);// 所有用于数组下标索引的都必须是usizegraph[u].push((v, w));}let mut dist = vec![MAX_VALUE; n + 1];  // dist[i]表示到节点i的最小距离let mut state = vec![0; n + 1];     // state[i]=0表示节点i没被确认最短路let mut cnt = 0;    // 表示有多少节点确认了最短路let mut heap = BinaryHeap::new();let mut res = 0;dist[k] = 0;heap.push(Reverse((0, k)));while heap.len() != 0 {// heap.pop直接获取元素本身,而不是元素的引用let Reverse(t) = heap.pop().unwrap_or(Reverse((0, 0)));let (d, u) = (t.0, t.1);// 如果u已经被确认最短路,那就直接跳过if state[u] == 1 {continue;}state[u] = 1;cnt += 1;res = res.max(dist[u]);// 更新u的所有下一个点for i in 0..graph[u].len() {// graph[u] = [(v,w),()...]let (v, w) = graph[u][i];if state[v] == 1 {continue;}if dist[u] + w < dist[v] {dist[v] = dist[u] + w;heap.push(Reverse((dist[v], v)));}}}if cnt != n {-1} else {res}}
}

mark一下rust圣经上的遍历语句
在这里插入图片描述
还有一个enumerate,拿的是下标和引用:

let mut v = vec![1, 3, 2];	// Vec<i32>
for (i, va) in v.iter().enumerate() {}

i是usize,va是&i32

方法二:实现邻接矩阵

这个我测了一下:
在这里插入图片描述
(这图怎么粘上来这么大,怀念以前可以直接调整图片大小的时候)

这个可以成功打印出3x2的矩阵,元素都是1.

To be continued…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/46699.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【项目实践】基于LSTM的一维数据扩展与预测

基于LSTM的一维数据拟合扩展 一、引(fei)言(hua) 我在做Sri Lanka生态系统服务价值计算时&#xff0c;中间遇到了一点小问题。从世界粮农组织(FAO)上获得Sri Lanka主要农作物产量和价格数据时&#xff0c;其中的主要作物Sorghum仅有2001-2006年的数据&#xff0c;而Millet只有…

算法通关村第4关【黄金】| 表达式问题

1. 计算器问题 思路&#xff1a;此题不考虑括号和负数情况&#xff0c;单纯使用栈即可解决。注意的是数字可能是多位数需要保留完整的num&#xff0c; 保留数字的前缀符号&#xff0c;当碰到加号&#xff0c;存进去&#xff1b;当碰到减号&#xff0c;存相反数进去&#xff1b;…

Apinto 网关进阶教程,插件开发入门指南

Apinto 是基于Go语言&#xff0c;由 Eolink 自主研发的一款高性能、可扩展、易维护的云原生 API 网关。Apinto 能够帮助用户简单、快速、低成本、低风险地实现&#xff1a;系统微服务化、系统集成、向合作伙伴、开发者开放功能和数据。 通过 Apinto&#xff0c;企业能够专注于…

【LeetCode-中等题】15. 三数之和

题目 题解一&#xff1a;双指针法 图解参考链接&#xff1a;画解算法&#xff1a;15. 三数之和 详解参考代码随想录讲的非常好 梦破碎的地方&#xff01;| LeetCode&#xff1a;15.三数之和 代码&#xff1a; class Solution {public List<List<Integer>> thre…

Codeforces Round 893 (Div. 2) A ~ C

比赛链接 A. Buttons 博弈、最优策略一定是先去按都能按的按钮&#xff0c;按完之后再按自己的。 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \nusing namespace std;typedef pair<int, int> PII; typede…

jstack(Stack Trace for Java)Java堆栈跟踪工具

jstack&#xff08;Stack Trace for Java&#xff09;Java堆栈跟踪工具 jstack&#xff08;Stack Trace for Java&#xff09;命令用于生成虚拟机当前时刻的线程快照&#xff08;一般称为threaddump或者javacore文件&#xff09;。 线程快照就是当前虚拟机内每一条线程正在执…

动手学深度学习-pytorch版本(二):线性神经网络

参考引用 动手学深度学习 1. 线性神经网络 神经网络的整个训练过程&#xff0c;包括: 定义简单的神经网络架构、数据处理、指定损失函数和如何训练模型。经典统计学习技术中的线性回归和 softmax 回归可以视为线性神经网络 1.1 线性回归 回归 (regression) 是能为一个或多个…

Linux系统的目录结构

file system hierarchy standard文件系统层级标准&#xff0c;定义了在类Unix系统中的目录结构和目录内容。 即让用户了解到已安装软件通常放置于哪个目录下。 Linux目录结构的特点 使用树形目录结构来组织和管理文件。 整个系统只有一个根目录&#xff08;树根&#xff09;&a…

记录几个Hudi Flink使用问题及解决方法

前言 如题&#xff0c;记录几个Hudi Flink使用问题&#xff0c;学习和使用Hudi Flink有一段时间&#xff0c;虽然目前用的还不够深入&#xff0c;但是目前也遇到了几个问题&#xff0c;现在将遇到的这几个问题以及解决方式记录一下 版本 Flink 1.15.4Hudi 0.13.0 流写 流写…

Flink之时间语义

Flink之时间语义 简介 Flink中时间语义可以说是最重要的一个概念了,这里就说一下关于时间语义的机制,我们下看一下下面的表格,简单了解一下 时间定义processing time处理时间,也就是现实世界的时间,或者说代码执行时,服务器的时间event time事件时间,就是事件数据中所带的时…

nginx代理webSocket链接响应403

一、场景 使用nginx代理webSocket链接&#xff0c;nginx响应403 1、nginx访问日志响应403 [18/Aug/2023:09:56:36 0800] "GET /FS_WEB_ASS/webim_api/socket/message HTTP/1.1" 403 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit…

【数据结构】循环队列

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

浏览器 - 事件循环机制详解

目录 1&#xff0c;浏览器进程模型进程线程浏览器的进程和线程1&#xff0c;浏览器进程2&#xff0c;网络进程3&#xff0c;渲染进程 2&#xff0c;渲染主线程事件循环异步同步 JS 为什么会阻塞渲染任务优先级 3&#xff0c;常见面试题1&#xff0c;如何理解 js 的异步2&#x…

❤ Vue工作常用的一些动态数据和方法处理

❤ Vue工作常用的一些动态数据和方法处理 &#xff08;1&#xff09;动态拼接相对路径结尾的svg 错误写法一 ❌ 正确写法 &#x1f646; <img :src"require(/assets//amazon/svg/homemenu${index}.svg)" style"height: 20px;display: block;margin: 0 au…

关于视频监控平台EasyCVR视频汇聚平台建设“明厨亮灶”具体实施方案以及应用

一、方案背景 近几年来&#xff0c;餐饮行业的食品安全、食品卫生等新闻频频发生&#xff0c;比如某火锅店、某网红奶茶&#xff0c;食材以次充好、后厨卫生被爆堪忧&#xff0c;种种问题引起大众关注和热议。这些负面新闻不仅让餐饮门店的品牌口碑暴跌&#xff0c;附带的连锁…

[JavaWeb]【二】Vue Ajax Elemnet Vue路由打包部署

目录 一 什么是Vue 1.1 Vue快速入门 1.2 常用指令 1.2.1 v-bind && v-model 1.2.2 v-on 1.2.3 v-if && v-show 1.2.4 v-for 1.2.5 案例 1.3 生命周期 二 Ajax 2.1 Ajax介绍 2.2 同步与异步 2.3 原生Ajax&#xff08;繁琐&#xff0c;过时了&#xff09…

手机技巧:分享五个非常实用的生活类APP

目录 1、我的桌面iScreen-桌面美化神器 2.Just Rain-创意听雨声APP 3.得言-美文句子神器 4、微手帐 5、暗盒-隐私保护神器 今天给大家整理5个非常实用的实用APP软件&#xff0c;感兴趣的朋友可以下载试试&#xff01; 1、我的桌面iScreen-桌面美化神器 我的桌面iScreen是一…

[uni-app] uview封装Popup组件,处理props及v-model的传值问题

文章目录 需求及效果遇到的问题解决的办法偷懒的写法 需求及效果 uView(1.x版本)中, 有Pop弹出层的组件, 现在有个需求是,进行简单封装,有些通用的设置不想每次都写(比如 :mask-custom-style"{background: rgba(0, 0, 0, 0.7)}"这种) 然后内部内容交给插槽去自己随…

系统架构设计专业技能 · 系统工程与系统性能

系列文章目录 系统架构设计专业技能 网络技术&#xff08;三&#xff09; 系统架构设计专业技能 系统安全分析与设计&#xff08;四&#xff09;【系统架构设计师】 系统架构设计高级技能 软件架构设计&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 …

2023年上半年软件设计师下午真题及答案解析

试题一(15分) 随着农业领域科学种植的发展&#xff0c;需要对农业基地及农事进行信息化管理&#xff0c;为租户和农户等人员提供种植相关服务&#xff0c;现欲开发农事管理服务平台&#xff0c;其主要功能是&#xff1a; (1)人员管理&#xff1a;平台管理员管理租户&#xff…