Day 03 | 链表专题与虚拟头节点

题目:leetcode 203 移除链表元素

题意:给定链表的头节点和目标值,删除链表中与目标值相等的元素,返回新的头节点(因为头节点可能就是要删除的元素)

思路1 不使用虚拟头节点,直接在原链表节点上操作

这样出现的问题是:删除头节点和删除其他节点的方式不同,需要 单独写删除头节点的操作

while(head != nullptr && head->val == val) {
    head = head->next;
}

注意:是while 而不是 if ,如一组数据 [1,1,1,1,1,1]  ,目标值 val = 1,那么我们要持续移除头节点,所以要用 whlle

还有一点是:删除节点只是让他指向了下一个位置,并没有真正删除,还需要内存释放,在C++中需要这样写,就是定义一个临时节点,通过它来间接删除(其他语言有内存回收机制,所以不需要写)

while (head != nullptr && head->val == val) {
    ListNode*  tmp  = head;
    head = head->next;
    delete tmp;
}

接下来是其他节点的删除:要注意的是 定义的 cur 节点是指向head 而不是 head->next,因为要删除元素需要知道它的上一个节点,如[1,4,2,3] val = 4, 我们要删除4,如果把cur 指向的是4 ,我们不知道它的上一个节点是谁,没有记录。而如果把cur 指向 head ,那么 4 就是cur->next,我们删除4 就只需要 让 cur->next = cur->next->next;

我当时的误区:误认为它的前一个节点就是head,不会变化

如果不是目标值,那么cur就会变化,它的上一个节点就不知道是谁了

完整代码如下:

/**
 * 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) {
        while(head != nullptr && head->val == val) {
            head = head->next;
        }
        ListNode* cur = head;
        while(cur != nullptr && cur->next != nullptr) {
            if (cur->next->val == val) {
                cur->next = cur->next->next;
            } else {
                cur = cur->next;
            }
        }
        return head;
    }
};

思路2: 采用虚拟头结点的方式,让 删除节点的方式可以统一

ListNode* dummy_head = new ListNode(0);
dummy_head->next = head;
ListNode* cur = dummy_head;

注意 :头结点的指针不能变得,最后我们要返回头节点,如果用头节点去遍历,头节点的指针就变来变去,所以需要定义一个临时指针cur

这里 同样注意是 cur = dummy_head 而不是 dummy_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* dummy_head = new ListNode(0);
        dummy_head->next = head;
        ListNode* cur = dummy_head;
        while(cur->next != nullptr) {
            if(cur->next->val == val) {
                cur->next = cur->next->next;
            } else {
                cur = cur->next;
            }
        }
        return dummy_head->next;
    }
};

 题目:leetcode 707 设计链表

 题意: 本题考查链表的基本操作,比较锻炼代码能力,注意这里的index 是从 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 < 0 || (index > (_size - 1))) {
            return -1;
        }
        LinkedNode* cur = _dummyhead->next;
        while (index) {
            cur = cur->next;
            index--;
        }
        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 < 0 || index > _size) {
            return;
        }
        LinkedNode* newnode = new LinkedNode(val);
        LinkedNode* cur = _dummyhead;
        while(index) {
            cur = cur->next;
            index--;
        }
        newnode->next = cur->next;
        cur->next = newnode;
        _size++;
    }
    
    void deleteAtIndex(int index) {
        if(index < 0 || index > _size  - 1) {
            return;
        }
        LinkedNode* cur = _dummyhead;
        while (index) {
            cur = cur->next;
            index--;
        }
       cur->next = cur->next->next;
       _size--;
    }

private:
    int _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);
 */

题目:leetcode 206 反转链表

 思路:双指针算法

定义两个指针,一个pre,一个cur,cur初始化为 head,让它指向head,由于反转之后原先的head指向了null,所以pre初始化为null

循环终止条件:当cur指针指向null的时候,pre指针就指向了尾节点,此时pre就是反转后的头节点直接返回就可以

注意:这里需要定义一个临时指针来存储cur->next,因为cur->next要指向pre,即cur->next = pre,此时cur->next值就改变了,而我们的cur接着移动到下一个节点即cur->next,所以需要临时定义一个temp来存cur->next,确保cur移动到下一个节点的值没有变

还有一点:是先让pre = cur ,然后让 cur = temp, 否则cur 的值已经变化了,pre就没有正确的指向cur的位置

/**
 * 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* pre = nullptr;
        ListNode* cur = head;
        while(cur != nullptr) {
            ListNode* temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值