代码随想录Day3 203.移除链表元素 707.设计链表 206.反转链表

92 阅读3分钟

Day3 203.移除链表元素 707.设计链表 206.反转链表

今日学习时长:3h

链表基础

链表的初始化

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

image-20230203220545857

203 移除链表元素

初始解答

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        while(head != nullptr && head -> val == val){
            head = head -> next;
            //头结点单独处理
        }
        ListNode* pre = head;
        while(pre != nullptr && pre -> next != nullptr){
            if(pre -> next -> val == val){
                pre -> next = pre -> next -> next;
                //不能移到下一个节点,出现连续的节点的val满足条件会有遗漏的情况出现
                //cpp需要处理删除的节点
            }else{
                pre = pre -> next;
            }
            
        }
        return head;
    }
};

特殊用例:

  1. 开头head的val为val
  2. 结尾head的val为val
  3. 连续几个节点的val为val

示例解答(虚拟头结点)

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;//返回时,要返回虚拟头结点的next
        delete dummyHead;
        return head;
    }
};

707 设计链表

漏洞百出的写法

class MyLinkedList {
public:
    ListNode * head;
    ListNode * tail;
    int length;
​
    MyLinkedList() {
        head = nullptr;
        tail = nullptr;
        length = 0;
    }
    
    int get(int index) {
        if(index < 0 || index > length - 1) return -1;
        int pre = 0;
        ListNode * cur = head;
        for(int i = 0; i < index; i++){
            cur = cur -> next;
        }
        return cur -> val;
    }
    
    void addAtHead(int val) {
        ListNode * add = new ListNode(val);
        add -> next = head;
        head = add;
        if(tail == nullptr) tail = add;
        length ++;
    }
    
    void addAtTail(int val) {
        ListNode *add = new ListNode(val);
        if(tail == nullptr){
            head = add;
            tail = add;
        }else{
            tail -> next = add;
            tail = tail -> next;
        }
        length ++;
    }
    
    void addAtIndex(int index, int val) {
        if(index <= 0) {
            addAtHead(val);
            return;
        }
        if(index == length) {
            addAtTail(val);
            return;     
        }
        int count = 0;
        ListNode * cur = head;
        ListNode * add = new ListNode(val);
        while(count < index - 1){
            cur = cur -> next;
            count ++;
        }
        add -> next = cur -> next;
        cur -> next = add;
        length ++;
    }
    
    void deleteAtIndex(int index) {
        if(get(index) == -1) return;
        length --;
        if(index == 0){
            ListNode * tmp = head;
            head = head -> next;
            delete tmp;
            return;
        }
        int count = 0;
        ListNode * cur = head;
        while(count < index - 1){
            cur = cur -> next;
            count ++;
        }
        ListNode * tmp = cur -> next;
        cur -> next = tmp -> next;
        //delete tmp;
        if(length == 0) {
            tail = nullptr;
            head = nullptr;
        }
    }
};
​
/**
 * 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);
 */

length没有及时加减

count在while循环中没有自增

tail在addAtHead中没有更新和添加

etc

链表写了不少次,但还是很生疏写不对

尝试用虚拟头结点书写+没有尾结点

class MyLinkedList {
​
public:
​
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val), next(nullptr){}
    };
​
    
​
    MyLinkedList() {
        _dummyHead = new LinkedNode(0);
        _size = 0;
    }
    
    int get(int index) {
        if(index < 0 || index > (_size - 1)){
            return -1;
        }
        LinkedNode * cur = _dummyHead -> next;
        while(index --){
            // index为0时不会进入循环
            cur = cur -> next;
        }
        return cur -> val;
    }
    
    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode -> next = _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 ++;
    }
    
    void addAtIndex(int index, int val) {
       if(index > _size) return;//勿漏题目条件
       if(index == _size) {
            addAtTail(val); 
            return;//没有及时return 造成了重复在tail末尾增加
       }
       if(index <= 0) {
            addAtHead(val);
            return;
       }
       LinkedNode* newNode = new LinkedNode(val);
       LinkedNode* cur = _dummyHead;
       while(index --){
           cur = cur -> next;
       }
       newNode -> next = cur -> next;
       cur -> next = newNode;
       _size ++;
    }
    
    void deleteAtIndex(int index) {
       if(get(index) == -1) return;
       LinkedNode* cur = _dummyHead;
       while(index --){
           cur = cur -> next;
       }
       LinkedNode* tmp = cur -> next;
       cur -> next = tmp -> next;
       delete tmp;
       _size --;
    }
​
    private:
    LinkedNode* _dummyHead;
    int _size;
};

标程中可以借鉴的地方

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转化为一种

206 反转链表

初始解法——记录数值

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        int a[5005];
        int size = 0;
        ListNode* cur = head;
        while(cur != nullptr){
            a[size] = cur -> val;
            size ++;
            cur = cur -> next; 
        }
        ListNode* newList= new ListNode(0);
        cur = newList;
        for(int i = 0; i < size; i++){
            ListNode * newNode = new ListNode(a[size - 1 - i]);
            cur -> next = newNode;
            cur = cur -> next;
        }
        return newList -> next;
    }
};

双指针法

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;
    }
};

递归法

class Solution {
public:
    ListNode* reverse(ListNode* pre,ListNode* cur){
        if(cur == NULL) return pre;
        ListNode* temp = cur->next;
        cur->next = pre;
        // 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步
        // pre = cur;
        // cur = temp;
        return reverse(cur,temp);
    }
    ListNode* reverseList(ListNode* head) {
        // 和双指针法初始化是一样的逻辑
        // ListNode* cur = head;
        // ListNode* pre = NULL;
        return reverse(NULL, head);
    }
​
};