算法练习之反转链表

比较久没有写算法题了。还是应该复习回顾一下,这次用新学的 rust 语言来解决算法问题。个人认为学习算法题目重要的不是解法,而是解法背后的思想。要从每一道题目中学习到解决问题的思路。

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

示例:

复制代码
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

限制:

0 <= 节点个数 <= 5000

反转链表可以说是计算机专业入门级最简单的算法了。我认为这道题目其实背后的思想是temp 交换。我们知道当交换,A、B两个变量的值的时候,需要引入一个额外变量 temp

temp = A

A = B

B = temp

同样的对于本地,我们需要引入一个 next/prev变量,来让我们反转的过程顺利进行

NULL 1->2->3->4->5->NULL

↑ ↑

prev current

NULL <- 1 2->3->4->5->NULL

↑ ↑ ↑

prev current next

NULL <- 1 2->3->4->5->NULL

↑ ↑

prev current

可以看出来,当我们形成出需要的反转链表时候,前半段与后半段就已经割裂出来,所以,我们需要三个变量,来保证我们仍然可以继续遍历。

rust 复制代码
pub struct Solution {}
impl Solution {
    // 需要搞明白,什么是 take
    // take 方法可以从 option 中取出值,为原来的 Option 变量留下 None 值,但原来的变量还有效
    // take 方法的原始值或者引用必须为mut 类型。
    // Takes the value out of the option, leaving a None in its place.
    pub fn reverse_list(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
        if head.is_none() {
            return None;
        }
        let mut prev = None;
        let mut current = head;
        while let Some(mut tmp) = current.take() {
            let next = tmp.next.take();
            tmp.next = prev.take();
            prev = Some(tmp);
            current = next;

        }
        return prev;
    }
}
rust 复制代码
fn list_node() {
    let tail = ListNode::new(1);
    let head = ListNode {
        val: 1,
        next: Some(Box::new(ListNode {
            val: 2,
            next: Some(Box::new(ListNode { val: 3, next: Some(Box::new(ListNode { val: 4, next: None })) })),
        })),
    };

    let mut revert_node = Solution::reverse_list(Some(Box::new(head)));
    /**
    as_ref是转引用函数,将具有所有权对象转换成引用对象,在不改变被转换对象的基础上产升一个引用对象
    as_ref并不是所有类型都默认支持,很多时候需要自己去声明。是 ASRef trait的公共接口方法,只有那些实现了 as_ref公共接口方法
    的类型磁能使用 as_ref,目前有 Option,Box,Result 这三种类型默认支持 as_ref
    */
    let mut cur = revert_node;
    // 如果选项是 Some 值,则返回 true
    while cur.is_some() {
        // 可以的看到,unwrap 使用了 cur 的所有权,所以。我们只能移动出来,在使用一次。
        let value = cur.unwrap();
        println!("{}",value.val);
        cur = value.next;
        // 而不能这样做
        // println!("{}", cur.unwrap().val);
        // cur = cur.unwrap().next
    }
}

使用 rust 的时候,比较麻烦的就是所有权问题。尤其是操作指针的时候。在执行

tmp.next.take()

的时候,需要写 take(),该方法的作用是,取出 option 中的数据,并将其至为 None。如果我们不这样做,会发现 tmp.next的所有权被转移给了 next 变量,下面将不能再给tmp.next赋值,而使用 take 方法则不会转移所有权。

相关推荐
福居路冥想的草莓44 分钟前
逆波兰表达式求值(中等)
数据结构
cdut_suye2 小时前
【Linux系统】从零开始构建简易 Shell:从输入处理到命令执行的深度剖析
java·linux·服务器·数据结构·c++·人工智能·python
yaoshengvalve2 小时前
V型球阀材质性能深度解析:专攻颗粒、料浆与高腐蚀介质的工业利器-耀圣
开发语言·网络·数据结构·c++·安全·材质
evolution_language2 小时前
LintCode第68题-二叉树的前序遍历,第67题-二叉树的后序遍历
数据结构·算法·新手必刷编程50题
是店小二呀3 小时前
【算法-哈希表】常见算法题的哈希表套路拆解
数据结构·c++·算法·散列表
jiunian_cn3 小时前
【c++】多态详解
java·开发语言·数据结构·c++·visual studio
究极无敌暴龙战神X6 小时前
hot100-子串-JS
javascript·数据结构·算法
zxctsclrjjjcph12 小时前
【高并发内存池】从零到一的项目之centralcache整体结构设计及核心实现
开发语言·数据结构·c++·链表
柃歌13 小时前
【LeetCode Solutions】LeetCode 176 ~ 180 题解
数据结构·数据库·sql·算法·leetcode
oioihoii14 小时前
C++23 std::tuple与其他元组式对象的兼容 (P2165R4)
c++·链表·c++23