Day3 链表 LeetCode 203 707 206

72 阅读3分钟

203. 移除链表元素

心得

  • 想到虚拟头结点,但是实际写的时候对于指针、结构、链表的的基本操作不熟悉,用错如指向结构的指针(*pt).val (*pt).next 和pt→val 和pt→next等同
  • 需要注意符合单链表结构的,从当前和next考虑,而不是prev和cur考虑(名称可能会议歧义)

题解

  • 如果采用正常方法就是区分头结点和其他,对于头结点直接后移即可,但要注意连续出现的情况,所以针对头结点处理是循环方式,其次使用当前结点和next符合题意的单链表,而不是用prev,虽然做的事情一样,但是名称会误导
  • 虚拟头结点注意返回值,在正常办法情况下head已经替换掉了,直接返回即可,但是统一处理的虚拟头结点中的head其实已经被next接管替换,所以需要重新替换,同时注意释放内存
/**
 * 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 != nullptr){
            if (cur->next->val == val){
                ListNode* temp = cur->next;
                cur->next = cur->next->next;
                delete temp;
            }
            else {
                cur = cur->next;
            }
        }

        head = dummyHead->next;
        delete dummyHead;

        return head;

    }
};

707. 设计链表

心得

  • 链表构造不熟悉,结构需要自己处理,同时规范的类相关要求不熟悉,比如命名规范等
  • 尤其看到函数多,有畏难情绪,其实mid难度函数这么多一般难度其实会降下来
  • 题目的规范性确实是个类的良好学习样例

题解

  • 为方便统一操作,构造虚拟头结点,对于输入size需要判断异常,再进行即可,对于特定位置需要先新建,然后加遍历到达的位置即可
  • 尤其需要注意前后赋值问题和循环退出条件
  • 注意需要遍历的位置基本都是dummyHead而不是对应next,其实就是判断0索引存不存在的情况
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 >= _size || index < 0) {
            return -1;
        }
        LinkedNode* cur = _dummyHead->next;
        while (index--){
            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 < 0) index = 0;
        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 (index >= _size || index < 0 ) {
            return;
        }
        LinkedNode* cur = _dummyHead;
        while (index--){
            cur = cur->next;
        }
        LinkedNode* temp = cur->next;
        cur->next = cur->next->next;
        delete temp;
        _size --;

    }

private:
    LinkedNode* _dummyHead; 
    int _size;
};

/**
 * 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. 反转链表

心得

  • 看到题目想到利用prev来保存前一个值,没有深入,深入应该能想到双指针,还是题目做少了,题感没上来
  • 想到保存的位置可能要用特殊如hash来保存,想太多了,刷题有时得看看题目难度,不要想太多

题解

  • 双指针法或者递归法,类似2个格子的滑动窗口逐次滑动左右指针替换,替换时类似swap需要temp,感觉就像数组swap的链表版本,直接用对应结构互换即可
/**
 * 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* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* cur = head;
        ListNode* temp;
        while (cur){
            temp = cur->next;
            cur->next = prev;
            prev = cur;
            cur = temp;
        }

        return prev;

    }
};