rust - 如何使用两个指针在 Rust 中迭代链表?
问题描述
我刚开始学习 Rust 语言,并尝试在 Leetcode 上做一些实践。我正在解决链接列表中间的问题。
解决方案就是使用慢速和快速指针。这是我在 Rust 中的代码:
#[derive(PartialEq, Eq, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>
}
impl ListNode {
#[inline]
pub fn new(val: i32) -> Self {
ListNode {
next: None,
val
}
}
}
struct Solution;
impl Solution {
pub fn middle_node(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let slow = &head;
let fast = &head;
while fast.is_some() && fast.unwrap().next.is_some() {
slow = &(slow.unwrap().next);
fast = &(fast.unwrap().next.unwrap().next);
}
*slow
}
}
但是,我遇到了很多编译器错误,例如:
--> src/main.rs:22:33
|
22 | while fast.is_some() && fast.unwrap().next.is_some() {
| ^^^^ cannot move out of borrowed content
我知道我违反了借款人检查规则,即我不能从不可变的 ref 中取出某些东西,但是我应该如何实现这个两指针实现呢?
任何建议都会有所帮助,在此先感谢。
解决方案
你是完全正确的,你的问题是你试图从借来的物体中移出一些东西。首先,让我们看一下您的签名。
pub fn middle_node(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
此函数获取head
并返回列表(某些子列表)的所有权。这无疑不是您想要的,因为它会使对列表的任何其他引用无效。在这种情况下,我们想借用参数并返回另一个引用。
pub fn middle_node(head: &Option<Box<ListNode>>) -> &Option<Box<ListNode>> {
没有所有权易手。并且没有所有权需要易手;调用者将在开始时拥有该列表,并在最后拥有该列表。
现在,您分配给fast
and slow
,因此它们需要是可变的。您不能重新分配给普通的let
.
let mut slow = head;
let mut fast = head;
(我还删除了&head
, 因为head
现在已经是参考,所以我们不再需要参考)
现在,最后,正如您所说,您每次都试图将值移出选项,这对借用检查器来说既不必要又令人困惑。幸运的是,Option
它提供了一种方便的方法来获取里面的引用。as_ref
把 anOption<T>
变成 a Option<&T>
,所以我们可以借用里面。我们需要as_ref
在每次我们之前unwrap
。例如,
while fast.is_some() && fast.as_ref().unwrap().next.is_some() {
(注意as_ref
) 和所有其他地方一样,你unwrap
是一个可选值。最后,返回的*slow
只是变成slow
,因为 againslow
已经是一个引用,我们现在正在返回一个引用。
可运行代码:
#[derive(PartialEq, Eq, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>
}
impl ListNode {
#[inline]
pub fn new(val: i32) -> Self {
ListNode {
next: None,
val
}
}
}
struct Solution;
impl Solution {
pub fn middle_node(head: &Option<Box<ListNode>>) -> &Option<Box<ListNode>> {
let mut slow = head;
let mut fast = head;
while fast.is_some() && fast.as_ref().unwrap().next.is_some() {
slow = &(slow.as_ref().unwrap().next);
fast = &(fast.as_ref().unwrap().next.as_ref().unwrap().next);
}
slow
}
}
fn arr_to_list(arr: &[i32]) -> Option<Box<ListNode>> {
let mut head = None;
for n in arr {
let mut new_node = ListNode::new(*n);
new_node.next = head;
head = Some(Box::new(new_node));
}
head
}
fn main() {
let node = arr_to_list(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
let mid = Solution::middle_node(&node);
println!("Middle node is {}", mid.as_ref().unwrap().val)
}
推荐阅读
- sql - golang sql指针值不断重复
- ios - Redis ios客户端以安全方式使用websocket
- reactjs - 无法读取 null 的属性“ownerDocument”
- module - 如何将 lmod 与鱼一起使用?
- flowtype - 带有联合参数的函数间接导致联合成员出现莫名其妙的错误
- database - 我如何阅读 blcokfile_xxxx
- python - SQLalchemy-如何从 sqlite 文件中提取表?
- api - YouTube 频道:列表 API 未按顺序返回
- firebase - Firebase 托管是否有请求限制?
- python-3.x - 有时在函数内部时,质数生成器最后不返回任何内容