代码随想录算法训练营Day 3|LeetCode203 移除链表元素、Leetcode707 设计链表、Leetcode206 反转链表

时间:2025-04-19 07:44:54

LeetCode203 移除链表元素

题目链接:移除链表元素

思路

因为该链表没有头结点,和考研时学的还有点出入,不过只是在处理首元结点上有点差异,单独处理即可,思路为:①若head->val==val,则直接将head指针后移并释放掉原首元结点即可;②若工作指针p->next->val==val,则将p->next=p->next->next,然后将原p->next释放。注:之前DS上的代码基本都是伪代码,对于指针置空或者边界条件都没有很严格,导致自己在这上面也是翻了些错——俩while循环里面的指针一开始都忘记加不为空的条件导致执行错误。

扩展思路:可以像之前学的,给该链表加上一个头结点Lnodehead,这样该链表后续所有结点删除操作都一致,无需再单独讨论首元结点,最后返回Lnodehead->next即可。

代码

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if (head == nullptr)
            return nullptr;
        while (head != nullptr && head->val == val) { //首元结点单独处理
            ListNode* temp = head;
            head = head->next;
            delete temp;
        }
        ListNode* p = head;
        while (p != nullptr && p->next != nullptr) {
            if (p->next->val == val) {
                ListNode* temp = p->next;
                p->next = p->next->next;
                delete temp;
            } else {
                p = p->next;
            }
        }
        return head;
    }
};

附随想录中带虚拟头结点代码

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
        dummyHead->next = head; // 将虚拟头结点指向head,这样方便后面做删除操作
        ListNode* cur = dummyHead;
        while (cur->next != NULL) {
            if(cur->next->val == val) {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            } else {
                cur = cur->next;
            }
        }
        head = dummyHead->next;
        delete dummyHead;
        return head;
    }
};

复杂度

时间复杂度 O(n)

空间复杂度O(1)

Leetcode707 设计链表

题目链接:设计链表

思路

本题较上题就采用了使用头结点的做法,并增加size字段以便于判断范围:①get,对于不在范围内index返回-1,在范围内便遍历到该处然后返回对应的值;②addAtHead,头插法,注意顺序防断链即可;③addAtTail,尾插法,一开始想减少时间耗费使用尾指针,但是头插按标号插入的情况尾指针不方便修改,于是改用直接遍历一遍链表,在末尾插入;④addAtIndex,按标号插入,遍历链表至index位置插入即可。实现头插和尾插时也可以直接调用该函数 ⑤deleteAtIndex,按标号删除,也是先查找到相应位置然后执行删除操作。

代码

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

    MyLinkedList() {
        Lnodehead = new ListNode(0);
        size = 0;
    }

    int get(int index) {
        if (index >= size || index < 0)
            return -1;

        ListNode* p = Lnodehead->next;
        while (index--) {
            p = p->next;
        }
        return p->val;
    }

    void addAtHead(int val) { //头插
        ListNode* temp = new ListNode(val);
        temp->next = Lnodehead->next; //注意顺序防止断链
        Lnodehead->next = temp;
        size++;
    }

    void addAtTail(int val) { //尾插
        ListNode* temp = new ListNode(val);
        ListNode* p = Lnodehead;
        while (p->next != nullptr) {
            p = p->next;
        }
        p->next = temp;
        size++;
    }

    void addAtIndex(int index, int val) {
        if (index <= size && index >= 0) {
            ListNode* temp = new ListNode(val);
            ListNode* p = Lnodehead;
            while (index--) {
                p = p->next;
            }
            temp->next = p->next;
            p->next = temp;
            size++;
        }
    }

    void deleteAtIndex(int index) {
        if (index < size && index >= 0) {
            ListNode* p = Lnodehead;
            while (index--) {
                p = p->next;
            }
            ListNode* temp = p->next;
            p->next = p->next->next;
            delete temp;
            size--;
        }
    }

private:
    int size;
    ListNode* Lnodehead;
};

复杂度

时间复杂度 get、addAtIndex、deleteAtIndex: O(index) 

                   addAtHead:O(1) 

                   addAtTail:O(len),其中len为链表长度

空间复杂度O(1)

Leetcode206 反转链表

题目链接:反转链表

思路

链表逆置,通过双指针可完成:设置工作指针p初始为head,p前置指针pre初始为Null。当p不为Null时循环,利用temp暂存p-next,防止断链,并将p->next=pre完成一个结点的逆置,最后更新pre和p。循环结束后pre即指向逆置后链表的头结点,返回。

代码

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* p=head;  //工作指针
        ListNode* pre=nullptr; //p前置
        while(p!=nullptr){
            ListNode* temp=p->next; //防断链
            p->next=pre;            //逆置
            //更新指针
            pre=p;
            p=temp;
        }
        return pre;
    }
};

复杂度

时间复杂度 O(n)

空间复杂度O(1)