文章链接:203.移除链表元素707.设计链表206.反转链表

203.移除链表元素

思路

因为在链表操作中,对头节点的处理与其他节点的处理不同,所以头节点需要特殊处理。

本文对链表的操作为设置一个虚拟头结点在进行删除操作。


代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummyhead = new ListNode(0); // 新建一个虚拟头节点
        dummyhead->next = 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; 
        // 不能在将dummyhead删除后访问它的next,所以要将dummyhead->next存起来
        // !!!注意!!!:在将一个节点释放后,不能访问它的接下来的节点
        delete dummyhead;
        return head;
    }
};

707.设计链表

代码

class MyLinkedList {
public:
    // 定义链表节点结构体
    struct LinkedNode{
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val), next(nullptr){}
    }; // 别忘了分号

    // 初始化链表
    MyLinkedList() {
        dummyhead = new LinkedNode(0); //定义一个虚拟头节点
        l_size = 0;
    }
    
    // 获得指定节点的值 
    int get(int index) {
        if(index > (l_size - 1) || index < 0){ // 下标从0开始
            return -1;
        }
        LinkedNode* cur = dummyhead->next;
        while(index--){ // 不能写--index
            cur = cur->next;
        }
        return cur->val;
    }
    
    // 头部插入节点
    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode->next = dummyhead->next; // 两个不能互换位置
        dummyhead->next = newNode;
        l_size++;
    }
    
    // 尾部插入节点
    void addAtTail(int val) {
        LinkedNode* newNode = new LinkedNode(val);

        // 查询操作:找链表原先的最后一个元素
        LinkedNode* cur = dummyhead;
        while(cur->next != nullptr){
            cur = cur->next;
        }
        cur->next = newNode; // 不用再将newNode的指针域指向NULL,因为本来就指向NULL
        l_size++;
    }
    
    // 指定节点前插入节点
    void addAtIndex(int index, int val) {
        if(index > l_size) return;
        if(index < 0) index = 0; // index小于0,则在头部插入节点
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = dummyhead;
        while(index--){
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        l_size++;
    }
    
    // 删除指定节点
    void deleteAtIndex(int index) {
        if(index > (l_size - 1) || index < 0){
            return;
        }
        LinkedNode* cur = dummyhead;
        while(index--){
            cur = cur->next; // 第n个节点是cur->next
        }
        LinkedNode* tmp = cur->next; // 用于释放内存
        cur->next = cur->next->next;
        delete tmp;
        tmp = NULL; // 避免tmp成为野指针
        l_size--;
    }

    // 打印链表
    void printLinkedList(){
        LinkedNode* cur = dummyhead;
        while(cur->next != NULL){
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << '\n';
    }

private:
    int l_size;
    LinkedNode* dummyhead;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */


206.反转链表

思路

首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null;

把 cur->next 节点用tmp指针保存;

将cur->next 指向pre ,此时已经反转了第一个节点了;

接下来循环。

代码

// 双指针法
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;
        ListNode* pre = NULL;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};