
安全两趟遍历实现无 unsafe推荐提交这是最符合 Rust 安全范式的写法逻辑清晰边界处理统一无需 unsafe 代码即可通过所有用例。rust// Definition for singly-linked list.// #[derive(PartialEq, Eq, Clone, Debug)]// pub struct ListNode {// pub val: i32,// pub next: OptionBox// }//// impl ListNode {// #[inline]// pub fn new(val: i32) - Self {// ListNode {// next: None,// val// }// }// }impl Solution {pub fn remove_nth_from_end(head: OptionBox, n: i32) - OptionBox {let mut dummy Box::new(ListNode::new(0));dummy.next head;let n n as usize;// 第一趟统计链表总长度 let mut len 0; let mut cur dummy.next; while let Some(node) cur { len 1; cur node.next; } // 第二趟移动到待删除节点的前驱节点 let mut cur mut dummy; for _ in 0..(len - n) { cur cur.next.as_mut().unwrap(); } // 执行删除take 拿走待删节点所有权拼接后继节点 let remove_node cur.next.take(); cur.next remove_node.unwrap().next; dummy.next }}一趟双指针实现unsafe双指针算法需要两个可变指针同时在链表上独立移动这直接违反 Rust 的借用检查规则同一作用域最多一个活跃可变引用。因此标准写法是使用裸指针 *mut T 绕过借用检查实现一趟遍历。rustimpl Solution {pub fn remove_nth_from_end(head: OptionBox, n: i32) - OptionBox {let mut dummy Box::new(ListNode::new(0));dummy.next head;let mut dummy Some(dummy);unsafe { // 裸指针规避借用检查 let mut fast: *mut OptionBoxListNode mut dummy; let mut slow: *mut OptionBoxListNode mut dummy; // fast 先走 n 步 for _ in 0..n { let node (*fast).as_mut().unwrap(); fast mut node.next as *mut _; } // 双指针同步前进直到 fast 指向链表末尾 None while (*fast).is_some() { fast mut (*fast).as_mut().unwrap().next as *mut _; slow mut (*slow).as_mut().unwrap().next as *mut _; } // slow 指向「待删节点前驱的 next 字段」直接修改完成删除 let target (*slow).take(); *slow target.unwrap().next; } dummy.unwrap().next }}关键要点虚拟头结点 dummy统一处理「删除头结点」的边界场景无需单独分支判断。Option::take()Rust 链表操作的惯用手法拿走待删除节点的所有权并原地置空再拼接后继节点安全完成删除。unsafe 的必要性Rust 借用规则不允许同一链表上同时存在两个活跃可变引用双指针一趟遍历必须用裸指针绕过检查。若追求代码安全性优先使用两趟遍历版本。复杂度两种实现时间复杂度均为 O(L)L 为链表长度空间复杂度 O(1)。