You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust如何正确返回修改后的链表?解决删除倒数第N个节点返回报错问题

Rust实现删除链表倒数第N个节点所有权问题解决方案

核心错误原因

  • 执行let mut new_cursor = head.unwrap();时,已经将head变量的所有权转移到了new_cursor中,后续再访问head自然会触发所有权已移动的编译错误
  • 直接操作链表节点的所有权值而非引用,无法保留根节点的有效访问路径,同时没有处理删除目标为头节点的边界场景
  • 统计长度时克隆整个链表属于不必要的性能开销,完全可以通过只读引用完成遍历计数

修正方案

采用虚拟哨兵节点统一删除逻辑,全程通过引用遍历避免所有权转移:

// LeetCode内置的ListNode定义,无需自行实现
// #[derive(PartialEq, Eq, Clone, Debug)]
// pub struct ListNode {
//   pub val: i32,
//   pub next: Option<Box<ListNode>>
// }
// impl ListNode {
//   #[inline]
//   fn new(val: i32) -> Self {
//     ListNode {
//       next: None,
//       val
//     }
//   }
// }

pub fn remove_nth_from_end(head: Option<Box<ListNode>>, n: i32) -> Option<Box<ListNode>> {
    // 创建虚拟哨兵节点,所有权全程持有整个链表的根
    let mut dummy = Some(Box::new(ListNode { val: 0, next: head }));
    let mut count = 0;

    // 第一次遍历统计总长度,用只读引用不转移所有权
    let mut cursor = dummy.as_ref();
    while cursor.unwrap().next.is_some() {
        count += 1;
        cursor = cursor.unwrap().next.as_ref();
    }

    // 计算要删除节点的前驱位置
    let step = count - n;
    // 第二次遍历找前驱节点,用可变引用方便修改指针
    let mut prev = dummy.as_mut();
    for _ in 0..step {
        prev = prev.unwrap().next.as_mut();
    }

    // 删除目标节点:直接修改前驱的next指针
    prev.unwrap().next = prev.unwrap().next.as_mut().unwrap().next.take();

    // 返回哨兵节点的next就是修改后的链表头
    dummy.unwrap().next
}

关键实现说明

  • 引入哨兵节点后,删除头节点和删除中间节点的逻辑完全一致,不需要单独做边界判断
  • 遍历过程中调用as_ref()/as_mut()获取Option的引用,不会转移所有权,全程链表的所有权都由dummy变量持有
  • 调用take()方法取出目标节点的next指针,同时把目标节点的next置为None,符合Rust的所有权规则

内容的提问来源于stack exchange,提问作者Marcus Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 17:54:04