代码随想录算法训练营第三天|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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值