203. 移除链表元素

题目描述

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

解题思路

链表题,hhhh,不是特别想用rust,不多说,直接操作ownersheip

#![allow(unused)]
fn main() {
struct Solution {}

// Definition for singly-linked list.
#[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
    }
  }
}

impl Solution {
    pub fn remove_elements(head: Option<Box<ListNode>>, val: i32) -> Option<Box<ListNode>> {
        let mut head = Some(Box::new(ListNode { val: 0, next: head }));
        let mut a: &mut Option<Box<ListNode>> = &mut head;
        while a.as_deref_mut().unwrap().next.is_some() {
            //         ^  Option<&mut ListNode>
            //    
            let v = a.as_deref_mut().unwrap().next.as_deref().unwrap().val;
            if v == val {
                let mut b = a.as_deref_mut().unwrap().next.take();
                let c = b.as_deref_mut().unwrap().next.take();
                a.as_deref_mut().unwrap().next = c;
            } else {
                let b = &mut a.as_deref_mut().unwrap().next;
                a = b;
            }
        }
        head.unwrap().next
    }
}
}

属实有点恶心了,看着太复杂了,这就是不用take的后果

学习感想

#![allow(unused)]

fn main() {
struct Solution {}

// Definition for singly-linked list.
#[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
    }
  }
}


impl Solution {
    pub fn remove_elements(head: Option<Box<ListNode>>, val: i32) -> Option<Box<ListNode>> {
        let mut dummyHead = Box::new(ListNode::new(0));
        dummyHead.next = head;
        let mut cur: &mut ListNode = dummyHead.as_mut();
	// 使用take()替换std::men::replace(&mut node.next, None)达到相同的效果,并且更普遍易读
        while let Some(nxt) = cur.next.take() {
            if nxt.val == val {
                cur.next = nxt.next;
            } else {
                cur.next = Some(nxt);
                cur = cur.next.as_mut().unwrap();   // coercion
                //           ^ Option<Box<ListNode>>
                //                    ^ Option<&mut Box<ListNode>>
                //                             ^ &mut Box<ListNode>
                //            deref   coerce ->     & mut ListNode
            }
        }
        dummyHead.next
    }
}
}

向这位老哥学习,使用take,管它用不用,先取下来再说。并且 先把option刨了

#![allow(unused)]

fn main() {
struct Solution {}

// Definition for singly-linked list.
#[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
    }
  }
}

impl Solution {
    pub fn remove_elements(mut head: Option<Box<ListNode>>, val: i32) -> Option<Box<ListNode>> {
        let mut res: Option<Box<ListNode>> = None;
        let mut ptr: &mut Option<Box<ListNode>> = &mut res;
        while let Some(mut x) = head {
            head = x.next.take();
            if x.val != val {
                *ptr = Some(x);
                ptr = &mut ptr.as_mut().unwrap().next;
            }
        }
        res
    }
}
}

链表的ownership还是非常容易理清楚的

一个Option不是owner没法直接unwrap,但是as_mut了之后可以随意unwrap,这也是容器穿透