如何使用两个指针在Rust中迭代链表?
我刚开始学习Rust lang,并尝试在Leetcode上进行一些练习。我正在解决这个问题 解决方法就是使用慢速和快速指针。这是我在Rust中的代码:如何使用两个指针在Rust中迭代链表?,rust,Rust,我刚开始学习Rust lang,并尝试在Leetcode上进行一些练习。我正在解决这个问题 解决方法就是使用慢速和快速指针。这是我在Rust中的代码: #[derive(PartialEq, Eq, Debug)] pub struct ListNode { pub val: i32, pub next: Option<Box<ListNode>> } impl ListNode { #[inline] pub fn new(val: i
#[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
}
}
我知道我违反了借款人检查规则,即我不能从不可变的ref中取出某些内容,但是我应该如何实现这个双指针实现呢
任何建议都会有帮助,提前谢谢。你的问题是你试图从借来的物品中搬出一些东西,这是完全正确的。首先,让我们看一下你的签名。
pub fn middle_node(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
没有所有权易手。没有所有权需要易手;调用方将在开始时拥有列表,在结束时拥有列表
现在,您分配给fast
和slow
,因此它们需要是可变的。您不能重新分配到普通的let
let mut slow = head;
let mut fast = head;
(我还删除了&head
,因为head
现在已经是一个引用,所以我们不再需要引用了)
最后,正如您所说,您每次都试图将该值移出该选项,这对借阅检查器来说既不必要又容易混淆。幸运的是,选项
提供了一种方便的方法来获取对内部的引用as_ref
采用了一个选项
并将其转换为选项
,因此我们可以借用内部。我们需要在每次展开之前将作为\u ref
。比如说,
while fast.is_some() && fast.as_ref().unwrap().next.is_some() {
(请注意作为_ref
)以及展开
的所有其他位置的可选值。最后,返回的*slow
变为slow
,因为slow
已经是一个引用,我们现在返回一个引用
可运行代码:
#[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)
}
#[派生(PartialEq、Eq、Debug)]
发布结构列表节点{
发布日期:i32,
下一步:选项
}
impl列表节点{
#[内联]
新发布(val:i32)->Self{
列表节点{
下一个:没有,
瓦尔
}
}
}
结构解决方案;
impl解决方案{
发布fn中间节点(标题:&选项)->&选项{
让mut slow=head;
让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);
}
缓慢的
}
}
fn排列到排列列表(排列:&[i32])->选项{
让mut head=None;
对于arr中的n{
让mut new_node=ListNode::new(*n);
new_node.next=头部;
head=Some(Box::new(new_节点));
}
头
}
fn main(){
让node=arr_to_list(&[1,2,3,4,5,6,7,8,9,10]);
让mid=解决方案::middle_节点(&node);
println!(“中间节点是{}”,mid.as_ref().unwrap().val)
}
你好,西尔维奥,非常感谢你的回答。我认为方法签名middle_node(head:&Option)->&Option是由Leetcode定义的,我可能应该向他们报告这个错误。而且,看起来像Option。由于_ref().unwrap()是一个常用场景,我想知道为什么我们没有一个方法在核心库中将它们组合在一起。谢谢。根据我的经验,unwrap
通常是不受欢迎的,除非是在这样的小程序中选项
有很多其他的窥视方式,不涉及恐慌(展开_或
,确定_或
,等等),所有这些都需要与_ref
调用相同的来确保借用。我同意你的观点,如果他们真的为该函数定义了自己的类型签名,应该向Leetcode报告这一点。他们可能只是针对所有的挑战这么做,而没有真正考虑它(如果你正在编写一个应该支持多种语言的挑战,那么这很容易做到),并且应该引起他们的注意。
while fast.is_some() && fast.as_ref().unwrap().next.is_some() {
#[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)
}