代码随想录打卡Day3

刷完题感觉自己链表的基础很不牢固。。

203.移除链表元素

这个比较简单,和之前删除数组中指定元素有点类似,但链表需要及时将对应的节点删除,而不是单纯的数值覆盖,这个题目的关键在于创建一个虚拟头节点,让头节点与中间节点,尾节点的删除操作完全一致,这样代码具有通用性。
这是我的代码,仅供参考。

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* fast = head;
        ListNode* slow = new ListNode();
        ListNode* result = slow;
        
        while(fast){
            if(fast -> val != val){
                slow -> next = fast;
                slow = slow -> next;
            }
            fast = fast -> next;
        }
        slow -> next = NULL;
        return result -> next;
    }
};

707.设计链表

这个主要是工作量大一点,非常建议用VS来debug,这一题花了我2个小时时间才通过。。。
感觉链表的增删查高度依赖于元素的下标,所以有必要创建一个临时变量来记录,另外,在头部插入,尾部插入,指定下标插入时,建议统一采用下标与链表长度比较的判断条件来实现,因为我没有采用统一的方式踩了雷。。。
这是我的代码,仅供参考。

class MyLinkedList {
public:
    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) {}
    };

    MyLinkedList() { //done
        this -> dummy = new ListNode(0);
        this -> len = 0;
    }
    
    int get(int index) {  //done
        if(index < 0 || index >= this -> len)
            return -1;
        ListNode* current = this -> dummy;

        int count = -1;
        while(count < index){
            count++;
            current = current -> next;
        }
        return current -> val;
    }
    
    void addAtHead(int val) {  //done
        ListNode* newhead = new ListNode(val, this -> dummy -> next);
        this -> dummy -> next = newhead;
        this -> len++;
    }
    
    void addAtTail(int val) {  //done
        ListNode* newtail = new ListNode(val);
        ListNode* current = this -> dummy;
        while(current -> next){
            current = current -> next;
        }
        current -> next = newtail;
        this -> len++;

    }
    
    void addAtIndex(int index, int val) {  //done
        if(index > this -> len)
            return ;
        int count = -1;
        ListNode* current = this -> dummy;
        while(count < index - 1){
            count++;
            current = current -> next;
        }
        ListNode* newnode = new ListNode(val, current -> next);
        current -> next = newnode;
        this -> len++;
    }
    
    void deleteAtIndex(int index) {
        if(index < 0 || index >= this -> len)
            return ;
        int count = -1;
        ListNode* current = this -> dummy;
        while(count < index - 1){  //定位到删除节点的前一个节点
            current = current -> next;
            count++;
        }
        
        current -> next = current -> next -> next;
        this -> len--;
    }
private:
    int len;  //链表长度
    ListNode* dummy;  //虚拟头节点
};

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

这个用暴力点的办法也能做,就是用一个向量,在遍历链表的同时依次将值填入,然后重新遍历链表,从后往前遍历向量,依次将值填入链表就可以。看完视频讲解以后感觉双指针也很简洁,前面的暴力法在于不改变节点的相对顺序,而改变里面的值,而双指针法则是不改变节点里存储的值,改变节点之间的相对顺序,递归有点晦涩难懂,但是理解了双指针的解法以后,递归的代码也很好写。

双指针法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        return reverseNode(NULL, head);

    }
    ListNode* reverseNode(ListNode* pre, ListNode* current){
        if(current == NULL)
            return pre;
        ListNode* temp = current -> next;
        current -> next = pre;
        pre = current;
        current = temp;
        return reverseNode(pre, current);
    }
};

递归法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        return reverseNode(NULL, head);

    }
    ListNode* reverseNode(ListNode* pre, ListNode* current){
        if(current == NULL)
            return pre;
        ListNode* temp = current -> next;
        current -> next = pre;
        pre = current;
        current = temp;
        return reverseNode(pre, current);
    }
};

基础不牢,地动山摇,这几个题目以后还得反复刷,特别是设计链表这一题,很考验基本功。

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值