LeetCode刷题(C++)-链表篇

链表

203.移除链表元素

普通方法:需要分头节点和非头节点,需要用一个cur指针来遍历,因为要返回头节点,所以不能用head来遍历,注意C++需要手动清除内存

/**
 * 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 != NULL && head->val == val){
            ListNode* tmp = head;
            head = head -> next;
            delete tmp;
        }
        //删除非头节点
        ListNode* cur = head;
        while(cur != NULL && cur->next != NULL){
            if(cur->next->val == val){
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            }else{
                cur = cur->next;
            }
        }
        return head;
    }
};

虚拟头节点法:加一个虚拟头节点,就可以统一以上两段代码,注意最后返回的是head = dummyHead->next,先保存head,再删dummyHead,再返回head

/**
 * 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, head);//设置一个虚拟头节点
       //dummyHead->next = head;
       ListNode* cur = dummyHead;

        while(cur != NULL && 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;
        delete dummyHead;
        return head;
    }
};//duotingl

707.设计链表

index范围:0~size-1。此处设置了一个虚拟头节点dummyHead,如果cur从dummpyHead开始遍历,那么最后cur指向index-1节点,如果cur从dummyHead->next遍历,那么cur最后指向index节点。注意边界处理问题,如删除的时候不能删除size节点,但是插入可以。

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 - 1) || index < 0){
            return -1;
        }
        LinkedNode *cur = _dummyHead -> next;
        while(index--){
            cur = cur -> next;
        }
        //此时cur指向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 > _size){
            return;
        }
        if(index < 0){
            index = 0;
        }
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(index--){
            cur = cur -> next;
        }
        //此时cur指向index-1节点
        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;
        }
        //此时cur指向index-1节点
        LinkedNode* tmp = cur -> next;
        cur -> next = cur -> next ->next;
        delete tmp;
        //delete命令指示释放了tmp指针原本所指的那部分内存,
        //被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,
        //如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针
        //如果之后的程序不小心使用了tmp,会指向难以预想的内存空间
        tmp = nullptr;
        _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);
 */

206.反转链表

双指针解法:

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

递归解法一:

/**
 * 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* reverse(ListNode* pre, ListNode* cur){
        if(cur==NULL) return pre;
        ListNode* tmp = cur->next;
        cur->next = pre;
        return reverse(cur, tmp);
    }
    ListNode* reverseList(ListNode* head) {
        return reverse(NULL, head);
    }
};

递归解法二:

前两个解法都是从前往后进行两两反转,此解法是从后往前进行两两反转

head == NULL || head->next == NULL是特殊情况的判断。同时head->next==NULL也是递归终止条件。

/**
 * 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) {
       if(head == NULL || head->next == NULL){
           return head;
       }
       ListNode* last = reverseList(head->next);
       head->next->next = head;
       head->next = NULL;
       return last;
    }
}; 

24.两两交换链表中的节点

画图理解

注意事项:最后别忘了cur = cur->next->next

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D6YAQSZq-1687509375200)(C:\Users\1\AppData\Roaming\Typora\typora-user-images\image-20230612141957125.png)]

/**
 * 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* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* cur = dummyHead;
        while(cur->next != nullptr && cur->next->next != nullptr){
            ListNode* tmp = cur->next;
            ListNode* tmp1 = cur->next->next->next;

            cur->next = cur->next->next;//步骤一
            cur->next->next = tmp;//步骤二
            cur->next->next->next = tmp1;//步骤三

            cur = cur->next->next;
        }
        return dummyHead->next;
    }
};

19.删除链表的倒数第n个节点

设置快慢指针,先让快指针移动n+1步,然后快慢指针再同时移动,这样快指针永远比慢指针在前面n+1步,当快指针到NULL的时候,慢指针就在倒数第n+1个位置,此处删除slow后一个节点即可。设置一个虚拟头节点,可以解决删除head的问题。

/**
 * 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* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* slow = dummyHead;
        ListNode* fast = dummyHead;
        /*while(n-- && fast != NULL){
            fast = fast->next;
        }
        fast = fast->next;*/
        for(int i = 0; i <= n; i++){
            fast = fast->next;
        }
        while(fast != NULL){
            slow = slow->next;
            fast = fast->next;
        }
        ListNode* tmp = slow->next;
        slow->next = tmp->next;
        delete tmp;
        tmp = NULL;
        return dummyHead->next;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值