如何使用Rust来克隆一个链表?

huangapple go评论79阅读模式
英文:

How can I use Rust to CLONE a linked list?

问题

I'm a rookie in Rust, and currently I'm actively using Rust to code LeetCode practice.

Now I'm working on this one, Copy List with Random Pointer, where nobody has even provided a Rust version answer.

I tried for a while but then I realized it's insanely hard for me to copy even a simple linked list in Rust.

Thanks for the help from @cafce25 that we can directly use .clone() to implement it, which is amazing. However, I'm wondering if there is any implementation that we don't need to use such a mighty weapon .clone() so that I could delve from this point.

Could anyone give me a favor? Thank you pretty much.

Some interfaces are provided as below and please feel free to modify function signatures.

#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
    pub val: i32,
    pub next: Option<Box<ListNode>>,
}

impl ListNode {
    pub fn new(val: i32) -> Self {
        ListNode {
            val,
            next: None,
        }
    }

    pub fn copyList(head: &Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        todo!();
    }
}
英文:

I'm a rookie in Rust, and currently I'm actively using Rust to code LeetCode practice.

Now I'm working on this one, Copy List with Random Pointer, where nobody has even provided a Rust version answer.

I tried for a while but then I realised it's insanely hard for me to copy even a simple linked list in Rust.

Thanks for the help from @cafce25 that we can directly use .clone() to implement it, which is amazing. However, I'm wondering if there is any implementation that we don't need to use such a mighty weapon .clone() so that I could delve from this point.

Could anyone give me a favour? Thank you pretty much.

Some interfaces are provided as below and please feel free to modify function signatures.

#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
    pub val: i32,
    pub next: Option<Box<ListNode>>,
}

impl ListNode {
    pub fn new(val: i32) -> Self {
        ListNode {
            val,
            next: None,
        }
    }

    pub fn copyList(head: &Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        todo!();
    }
}

答案1

得分: 2

Sure, here's the translated content:

不过,我在想是否有一种实现方式,我们不需要使用如此强大的 clone() 方法,这样我就可以从这一点深入。

首先,将 copyList 实际上获取列表节点本身的引用似乎是合理的,更符合惯用命名的是 copy_list

pub fn copy_list(head: &ListNode) -> ListNode {
    todo!()
}

(末尾没有 ;,因为我们希望返回一个结果,分号会使函数返回 ())。第一步是(不一定需要,但很有用)对参数进行模式匹配,我们也知道最终要返回一个 ListNode,所以让我们在那里构建它:

pub fn copy_list(head: &ListNode) -> ListNode {
    let ListNode { val, next } = head;
    let copied_next = todo!();
    ListNode { val: todo!(), next: copied_next }
}

剩下的是计算 copied_next(好吧,还有 val,但它要简单得多)。我不会为你提供完整的代码,但提供一些提示:

  1. 考虑 nextcopied_next 的类型;
  2. 您可以对 next 进行模式匹配,或者使用 Option::mapBox::map
  3. 您将在模式匹配或 map 的参数内的某个地方递归调用 copy_list

(而且简单地使用 next.clone() 也可以工作,并且大致上就是生成的 clone() 函数所做的事情,这也是它克隆整个列表的原因。)

英文:

> However, I'm wondering if there is any implementation that we don't need to use such a mighty weapon .clone() so that I could delve from this point.

First of all, it seems reasonable for copyList to actually take a reference to a list node itself, and the more idiomatic name is copy_list:

    pub fn copy_list(head: &ListNode) -> ListNode {
        todo!()
    }

(no ; at the end because we want to return a result, and the semicolon would make the function return ()). The first step is (not necessarily, but it's useful) to pattern-match the argument, and we also know we want to return a ListNode at the end, so let's construct it there:

    pub fn copy_list(head: &ListNode) -> ListNode {
        let ListNode { val, next } = head;
        let copied_next = todo!();
        ListNode { val: todo!(), next: copied_next }
    }

What remains is to calculate copied_next (ok, and val, but it's much simpler). I won't give you the full code for it, but some hints:

  1. Consider the types of next and copied_next;
  2. You can use either pattern matching on next or Option::map and Box::map;
  3. You'll call copy_list recursively somewhere inside that pattern match or map's argument.

(And simply next.clone() would work too, and is approximately what the generated clone() function does, which is why it clones the entire list.)

答案2

得分: 0

以下是您要翻译的内容:

感谢@Alexey Romanov的启发。经过数小时的调试,我实现了一种简单的克隆链表的方法,如下所示:

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct ListNode {
    pub val: i32,
    pub next: Option<Box<ListNode>>,
}

impl ListNode {
    pub fn new(val: i32) -> Self {
        ListNode {
            val,
            next: None,
        }
    }

    pub fn clone_linked_list(mut head: &Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        let mut dummy = Box::new(ListNode::new(-1));
        let mut pre = &mut dummy; 
        while let Some(node) = head {
            let new_node = Box::new(ListNode::new(node.val));
            pre.next.replace(new_node);
            pre = pre.next.as_mut().unwrap();
            head = &node.next;
        }
        dummy.next
    }
}

请随时提出任何建议。非常感谢。

英文:

Thanks for the inspiration from @Alexey Romanov. After several hours of debugging, I implemented a plain way to clone a linked list as below:

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct ListNode {
    pub val: i32,
    pub next: Option&lt;Box&lt;ListNode&gt;&gt;,
}

impl ListNode {
    pub fn new(val: i32) -&gt; Self {
        ListNode {
            val,
            next: None,
        }
    }

    pub fn clone_linked_list(mut head: &amp;Option&lt;Box&lt;ListNode&gt;&gt;) -&gt; Option&lt;Box&lt;ListNode&gt;&gt; {
        let mut dummy = Box::new(ListNode::new(-1));
        let mut pre = &amp;mut dummy; 
        while let Some(node) = head {
            let new_node = Box::new(ListNode::new(node.val));
            pre.next.replace(new_node);
            pre = pre.next.as_mut().unwrap();
            head = &amp;node.next;
        }
        dummy.next
    }
}

Please feel free to give any suggestions. Thank you a lot.

huangapple
  • 本文由 发表于 2023年5月6日 16:10:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76187824.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定