Rust踩雷笔记(5)——刷点链表的题(涉及智能指针Box,持续更新)

这篇具有很好参考价值的文章主要介绍了Rust踩雷笔记(5)——刷点链表的题(涉及智能指针Box,持续更新)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

只能说Rust链表题的画风和C++完全不一样,作为新手一时间还不太适应,于是单独为链表、智能指针开一篇,主要记录leetcode相关题型的答案以及注意事项。

🍑关键操作
as_ref()Option<T>&Option<T>或者&mut Option<T>转换为Option<&T>
as_mut()Option<T>&mut Option<T>转换为Option<&mut T>,不能对&Option<T>进行转换
⭐️以及注意&&mut叫做借用是非常形象的,既然是借用他人的物品,就不能转移他人物品的所有权
如果要拿走他人物品的所有权,请使用take()
⚠️l1 = p.next这个操作是希望把节点p的next赋给l1,但实际上如果p是对Box<ListNode>的可变借用,就会报错,因为这个过程会有所有权转移,p既然是借用,它就无权处置“物主”拥有的物品。所以此时用take()l1 = p.next.take()表示通过p这个借用,将所有权“拿走”给l1,并将p.next设置为None总之如果要通过借用来转移所有权,可以使用take()

leetcode 2 两数相加——模式匹配+单链表+Box

⭐️两个注意点
🍉里面有官方提供的单链表的实现,可以参考下;
🍉遍历链表可以用loop+match模式匹配的方式

// 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 add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        let mut t = (l1, l2, 0, 0);
        let mut result = None;
        let mut tail = &mut result;
        loop {
            t = match t {
                (None, None, _, 0) => break,
                (Some(l1), Some(l2), _, mut carry) => {
                    let temp = l1.val + l2.val + carry;
                    let res_temp = temp % 10;
                    carry = temp / 10;
                    (l1.next, l2.next, res_temp, carry)
                }
                (Some(l), None, _, mut carry) | (None, Some(l), _, mut carry) => {
                    let temp = l.val + carry;
                    let res_temp = temp % 10;
                    carry = temp / 10;
                    (l.next, None, res_temp, carry)
                }
                (None, None, _, carry) => {
                    (None, None, carry, 0)
                }
            };
            *tail = Some(Box::new(ListNode::new(t.2)));
            tail = &mut tail.as_mut().unwrap().next;
        }
        result
    }
}

🍉#[inline] 是什么?
是Rust 中的一个属性,用于提示编译器尝试对函数进行内联展开优化。 内联展开是一种优化技术,可以将函数调用的地方替换为函数体的内容,减少了函数调用的开销,提高代码的执行速度。 通过在函数定义之前使用 #[inline] 属性,你可以向编译器发出建议,让它在合适的情况下尝试内联展开函数。

另一个解法,更像是C++或者Java选手的思维文章来源地址https://www.toymoban.com/news/detail-671445.html

impl Solution {
    pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        let (mut l1, mut l2) = (l1, l2);
        let mut head = Box::new(ListNode::new(0));
        let mut p = &mut head;
        let mut carry = 0;
        let mut temp = 0;
        while let (Some(node1), Some(node2)) = (l1.as_ref(), l2.as_ref()) {
            temp = node1.val + node2.val + carry;
            p.next = Some(Box::new(ListNode::new(temp % 10)));
            p = p.next.as_mut().unwrap();
            carry = temp / 10;
            l1 = l1.unwrap().next;
            l2 = l2.unwrap().next;
        }
        while let Some(node) = l1.as_ref() {
            temp = node.val + carry;
            p.next = Some(Box::new(ListNode::new(temp % 10)));
            p = p.next.as_mut().unwrap();
            carry = temp / 10;
            l1 = l1.unwrap().next;
        }
        while let Some(node) = l2.as_ref() {
            temp = node.val + carry;
            p.next = Some(Box::new(ListNode::new(temp % 10)));
            p = p.next.as_mut().unwrap();
            carry = temp / 10;
            l2 = l2.unwrap().next;
        }
        if carry != 0 {
            p.next = Some(Box::new(ListNode::new(carry)));
            p = p.next.as_mut().unwrap();
        }
        head.next
    }
}

⭐️⭐️⭐️leetcode 21 合并有序链表——as_ref()、as_mut()、take()的使用

// 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 {
    // 对于链表而言,下面两个操作非常关键
    // as_ref()将Option<T>、&Option<T>或者&mut Option<T>转换为Option<&T>
    // as_mut()将Option<T>、&mut Option<T>转换为Option<&mut T>,不能对&Option<T>进行转换
    // ⭐️以及注意&和&mut叫做借用是非常形象的,既然是借用他人的物品,就不能转移他人物品的所有权
    // 如果要拿走他人物品的所有权,请使用take()
    
    // 堆上创建头结点
    pub fn merge_two_lists(mut l1: Option<Box<ListNode>>, mut l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        // 对于链表而言,下面两个操作非常关键
        // as_ref()将Option<T>、&Option<T>或者&mut Option<T>转换为Option<&T>
        // as_mut()将Option<T>、&mut Option<T>转换为Option<&mut T>,不能对&Option<T>进行转换
        // ⭐️以及注意&和&mut叫做借用是非常形象的,既然是借用他人的物品,就不能转移他人物品的所有权
        // 如果要拿走他人物品的所有权,请使用take()
        
        // 堆上创建头结点
        let mut head = Box::new(ListNode::new(0));
        let mut p = &mut head;  // 尾节点的可变借用
        while let (Some(node1), Some(node2)) = (l1.as_ref(), l2.as_ref()) {
            if node1.val < node2.val {
                p.next = l1;
                p = p.next.as_mut().unwrap();
                l1 = p.next.take();	// 将p.next拥有的转移给l1,并设置p.next为None
            }
            else {
                p.next = l2;
                p = p.next.as_mut().unwrap();
                l2 = p.next.take();
            }
        }
        if l1.is_some() {
            p.next = l1;
        }
        else {
            p.next = l2;
        }
        head.next
    }
}

到了这里,关于Rust踩雷笔记(5)——刷点链表的题(涉及智能指针Box,持续更新)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法通关村第一关---链表经典问题之两个链表的第一个公共节点笔记

    源码地址:GitHub-算法通关村 1.hash 2.集合 3.栈 4.双指针

    2024年02月16日
    浏览(44)
  • 青岛大学_王卓老师【数据结构与算法】Week04_04_双向链表的插入_学习笔记

    本文是个人学习笔记,素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享,另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权,请留言作删文处理。 课程视频链接: 数据结构与算法基础–第04周04–2.5.4双向链表2–双向链表

    2024年02月12日
    浏览(58)
  • 详解链表oJ<反转链表,链表的中间节点及链表的回文>

    hello,大家好,这里是Dark FlameMaster,今天和大家分享的是有关数据结构链表的几道题目,链表的中间节点,反转链表及判断链表是否为回文结构,放在一起讲解会印象更加深刻。 链接:链表的中间节点 分析:  如果想要得到链表的中间节点,最简单的思路就是从头结点遍历整

    2024年02月08日
    浏览(71)
  • 【数据结构】反转链表、链表的中间节点、链表的回文结构(单链表OJ题)

    正如标题所说,本文会图文详细解析三道单链表OJ题,分别为:  反转链表 (简单)  链表的中间节点 (简单)  链表的回文结构 (较难) 把他们放在一起讲的原因是:  反转链表 和  链表的中间节点 是  链表的回文结构 的基础 为什么这样说?请往下看: 目录 1. 反转链

    2024年02月13日
    浏览(72)
  • 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。

    /**  * Definition for singly-linked list.  * struct ListNode {  *     int val;  *     ListNode *next;  *     ListNode(int x) : val(x), next(NULL) {}  * };  */ class Solution { public:     ListNode* reverseList(ListNode* head) {              } };

    2024年02月22日
    浏览(49)
  • 【链表OJ 3】链表的中间结点

    前言:          本文收录于http://t.csdn.cn/n6UEP数据结构刷题的博客中,首先欢迎大家的来访,其次如有错误,非常欢迎大家的指正!我会及时更正错误! 目录 一.链表的中间结点  1.1原理:快慢指针的使用 链表元素个数为奇数时 链表元素个数为偶数时 1.2循环条件问题? 来源:87

    2024年02月14日
    浏览(50)
  • 【链表OJ题 6】链表的回文结构

    目录 题目来源: 代码实现: 思路分析: 实现过程: 链表的回文结构_牛客题霸_牛客网 (nowcoder.com) 题目描述: 本题的难点在于时间复杂度为O(n),空间复杂度为O(1)。 因为回文结构是正着读反着读是一样的,因此我们 找到链表的中间结点,然后从中间节点开始逆置到尾结点,

    2024年02月06日
    浏览(40)
  • <数据结构> 链表 - 链表的概念及结构

    概念: 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的 逻辑顺序 是通过链表中的 指针链接 次序实现的 1、链表由一系列结点(链表中每一个元素称为结点)组成。 2、结点可以在运行时动态(malloc)生成。 3、每个结点包括两个部分:一个是存储数据元素的

    2023年04月09日
    浏览(46)
  • 【Leetcode】反转链表 合并链表 相交链表 链表的回文结构

      目录 一.【Leetcode206】反转链表 1.链接 2.题目再现  3.解法A:三指针法 二.【Leetcode21】合并两个有序链表 1.链接 2.题目再现  3.三指针尾插法 三.【Leetcode160】相交链表 1.链接 2.题目再现 3.解法 四.链表的回文结构 1.链接 2.题目再现  3.解法 1.链接 反转链表 2.题目再现  3.解法

    2024年02月02日
    浏览(50)
  • 数据结构----链表介绍、模拟实现链表、链表的使用

    ArrayList底层使用连续的空间,任意位置插入或删除元素时,需要将该位置后序元素整体往前或者往后搬移,故时间复杂度为O(N) 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后

    2024年02月21日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包