Day4 链表part01 Leetcode 203.移除链表

Leetcode 203.移除链表

这题主要设计两种方法:

  • 直接使用原来的链表来进行删除操作。其需要分类为:1.删除头节点 2.删除中间节点
  • 设置一个虚拟头结点在进行删除操作。

直接使用原来链表进行删除操作,完整代码如下:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        //直接进行使用原来链表进行操作
        //删除头节点
        while(head != NULL && head->val == val){
            ListNode* tmp = head; //引入tmp防止内存泄漏
            head = head->next; 
            delete tmp; //释放内存
        }
        //删除非头节点
        ListNode* cur =head; 
        while(cur != NULL && cur->next != NULL){
            if(cur->next->val == val){
                ListNode* tmp = cur->next; //引入tmp防止内存泄漏
                cur->next = cur->next->next; 
                delete tmp; //释放内存
            }
            else{
                cur=cur->next; 
            }
        }
        return head; 
    }
};

使用虚拟头节点,代码如下:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        //虚拟头节点
        ListNode* dummyhead = new ListNode(0); 
        dummyhead->next = head; 
        ListNode* cur = dummyhead; 
        while(cur->next != nullptr){
            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; 
    }
};

在学习之中遇到2个问题(供大家参考学习):

其一,为什么不直接写 head = head->next;,而要引入一个临时指针 tmp

答:其实是因为C++动态内存管理问题,需要手动释放内存,防止内存泄漏问题。

其二,为什么需要单独设立一个cur指针变量?

答:1.保护头指针head,确保链表有效。2.避免直接操作头指针带来风险。(简单来说:头节点改了,那还能叫头吗)

leetcode.707设计链表

非常基本且有些枯燥的内容,其中的注意事项均已下在代码注释中

class MyLinkedList {
public:
    struct LinkedNode {
        int val;               // 节点存储的值
        LinkedNode* next;      // 指向下一个节点的指针

        // 构造函数
        LinkedNode(int val): val(val), next(nullptr) {}
    };

    MyLinkedList() {
        dummyHead = new LinkedNode(0); // 初始化虚拟头节点
        size = 0;
    }

    // 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点
    int get(int index) {
        if (index > (size - 1) || index < 0) {
            return -1;
        }
        LinkedNode* cur = dummyHead->next;
        while (index--) { // 注意这里是 index--,而不是 --index
            cur = cur->next;
        }
        return cur->val;
    }

    // 头部插入
    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode->next = this->dummyHead->next;
        dummyHead->next = newNode;
        size++;
    }

    // 尾部插入
    void addAtTail(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = dummyHead;
        while (cur->next != nullptr) {
            cur = cur->next;
        }
        cur->next = newNode;
        size++;
    }

    // 在第 index 个节点之前插入
    // 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
    // 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
    // 如果index大于链表的长度,则返回空
    // 如果index小于0,则在头部插入节点
    void addAtIndex(int index, int val) {
        if (index > size) return;
        if (index < 0) index = 0;

        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = dummyHead;
        while (index--) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        size++;
    }

    // 删除第 index 个节点
    void deleteAtIndex(int index) {
        if (index >= size || index < 0) {
            return;
        }
        LinkedNode* cur = dummyHead;
        while (index--) {
            cur = cur->next;
        }
        LinkedNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        //delete命令指示释放了tmp指针原本所指的那部分内存,
        //被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,
        //如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针
        //如果之后的程序不小心使用了tmp,会指向难以预想的内存空间
        tmp = nullptr; // 避免野指针
        size--;
    }

private:
    int size;               // 链表的长度
    LinkedNode* dummyHead;  // 虚拟头节点
};

你可能感兴趣的:(Leetcode,leetcode,链表,算法)