代码随想录算法训练营第三天|Leetcode203.移除链表元素 Leetcode707.设计链表 Leetcode206.反转链表

Leetcode203.移除链表元素

题目链接

从此题开始我们接触到链表这一新的数据结构,注意链表的定义,基础内容不做过多描述

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(nullptr) {}
};

关键词:虚节点

题目思路:首先设置虚节点保证头节点的操作与后续节点相同,然后通过遍历链表解决问题,注意p节点的更新操作与目标节点的删除操作是并列关系,要考虑到删除后的节点依旧是目标节点的情况

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode *dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode *p = nullptr;
        p = dummyHead;
        while (p != nullptr && p->next != nullptr) {
            if (p->next->val == val) {
                ListNode *pre = p->next;
                p->next = p->next->next;
                delete pre;
            }
            else {
                p = p->next;
            }
        }
        head = dummyHead->next;
        delete dummyHead;
        return head;
    }
};

反思:注意new函数的理解与使用

new函数

Leetcode707.设计链表

题目链接

该题是一些链表基础功的体现,注意虚节点的使用

处理问题的难点是如何判断索引是否有效,同时我们以索引作为循环终止的条件

在对链表进行遍历时类比数组的操作,不过是稍微繁琐一些

class MyLinkedList {
public:
    struct ListNode {
        int val;
        ListNode *next;
        ListNode(int val):val(val), next(nullptr){}
    };

    MyLinkedList() {
        _dummyHead = new ListNode(0);
        _size = 0;
    }
    
    int get(int index) {
        if (index < 0 || index > _size - 1) return -1;
        int result = 0;
        ListNode *cur = _dummyHead;
        while (index >= 0) {
            cur = cur->next;
            result = cur->val;
            index--;
        }
        return result;
    }
    
    void addAtHead(int val) {
        ListNode *cur = new ListNode(val);
        cur->next = _dummyHead->next;
        _dummyHead->next = cur;
        _size++;
    }
    
    void addAtTail(int val) {
        ListNode *p = new ListNode(val);
        ListNode *cur = _dummyHead;
        while (cur != nullptr && cur->next != nullptr) {
            cur = cur->next;
        }
        cur->next = p;
        _size++;
    }
    
    void addAtIndex(int index, int val) {
        if (index > _size) return;
        else {
            if (index == _size) {
                ListNode *cur = _dummyHead;
                while (cur != nullptr && cur->next != nullptr) {
                    cur = cur->next;
                }
                ListNode *p = new ListNode(val);
                cur->next = p;
                _size++;
                return;
                }
            if (index <= 0) {
            ListNode *p = new ListNode(val);
            p->next = _dummyHead->next;
            _dummyHead->next = p;
            _size++;
            return;
            }
        }
        ListNode *p = new ListNode(val);
        ListNode *cur = _dummyHead;
        while (index > 0) {
            cur = cur->next;
            index--;
        }
        p->next = cur->next;
        cur->next = p;
        _size++;
    }
    
    void deleteAtIndex(int index) {
        if (index < 0 || index > _size - 1) return;
        ListNode *cur = _dummyHead;
        while (index > 0) {
            cur = cur->next;
            index--;
        }
        ListNode *p = cur->next;
        cur->next = cur->next->next;
        delete p;
        _size--;
    }

private:
    ListNode *_dummyHead;
    int _size;
};

反思:对于c++语言本身不够了解,需要加强学习相关语法知识,类的基本操作

Leetcode206.反转链表

题目链接

关键词:递归

题目思路:借助这道题目理解递归函数的使用,使用关键是抽象函数的功能而忽略函数的实现细节,把函数理解为一个组件,不过我们是在未完成函数细节的情况下便将其作为一个组件使用,用于减小问题规模直到答案显而易见

比如此题,反转链表可以转化为反转以head->next为头节点的链表后把原head变为反转后链表的尾节点,注意我们反转链表之后(以示例1为例)head->next->val = 2这一点并未发生变化,故而有了我们的答案

注意此处时间复杂度的分析,递归函数时间复杂度=递归次数*单次函数时间复杂度

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return head;
        ListNode *newHead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return newHead;
    }
};

反思:递归函数代码形式简洁,但是理解难度大,效率一般

今日学习时间:2.5h

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Rust 是一种现代的编程语言,特别适合处理内存安全和线程安全的代码。在 LeetCode 中,链表是经常出现的题目练习类型,Rust 语言也是一种非常适合处理链表的语言。接下来,本文将从 Rust 语言的特点、链表的定义和操作,以及 Rust 在 LeetCode链表题目的练习等几个方面进行介绍和讲解。 Rust 语言的特点: Rust 是一种现代化的高性能、系统级、功能强大的编程语言,旨在提高软件的可靠性和安全性。Rust 语言具有如下几个特点: 1. 内存安全性:Rust 语言支持内存安全性和原语级的并发,可以有效地预防内存泄漏,空悬指针以及数据竞争等问题,保证程序的稳定性和可靠性。 2. 高性能:Rust 语言采用了“零成本抽象化”的设计思想,具有 C/C++ 等传统高性能语言的速度和效率。 3. 静态类型检查:Rust 语言支持静态类型检查,可以在编译时检查类型错误,避免一些运行时错误。 链表的定义和操作: 链表是一种数据结构,由一个个节点组成,每个节点保存着数据,并指向下一个节点。链表的定义和操作如下: 1. 定义:链表是由节点组成的数据结构,每个节点包含一个数据元素和一个指向下一个节点的指针。 2. 操作:链表的常用操作包括插入、删除、查找等,其中,插入操作主要包括在链表首尾插入节点和在指定位置插入节点等,删除操作主要包括删除链表首尾节点和删除指定位置节点等,查找操作主要包括根据数据元素查找节点和根据指针查找节点等。 Rust 在 LeetCode链表题目的练习: 在 LeetCode 中,链表是常见的题目类型,而 Rust 语言也是一个非常适合练习链表题目的语言。在 Rust 中,我们可以定义结构体表示链表的节点,使用指针表示节点的指向关系,然后实现各种操作函数来处理链表操作。 例如,针对 LeetCode 中的链表题目,我们可以用 Rust 语言来编写解法,例如,链表,合并两个有序链表,删除链表中的重复元素等等,这样可以更好地熟悉 Rust 语言的使用和链表的操作,提高算法和编程能力。 总之,在 Rust 中处理链表是非常方便和高效的,而 LeetCode 中的练习也是一个非常好的机会,让我们更好地掌握 Rust 语言和链表数据结构的知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值