代码随想录算法训练营三天 |链表理论基础 Leetcode 203.移除链表元素、Leetcode 707.设计链表、Leetcode 206.反转链表

本文介绍了链表的基本概念,包括链表理论、LeetCode中的两个问题(移除链表元素和设计链表),展示了两种方法(直接删除和虚拟头节点法)处理移除元素问题,以及反转链表的双指针法和递归法。强调了时间复杂度和空间复杂度的分析。
摘要由CSDN通过智能技术生成

链表理论基础

文章链接:链表理论基础
思想:链表是线性表的链式表示

Leetcode 203.移除链表元素

题目链接:203.移除链表元素
解题思路:利用虚拟头节点进行链表的删除操作,可以统一删除操作,并不用为删头节点写特判

直接删除法:

/**
 * 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;
            tmp = NULL;
        }

        ListNode* cur = head;
        while(cur != NULL && cur->next != NULL) {
            if(cur->next->val == val) {
                cur->next = cur->next->next;
            } else {
                cur = cur->next;
            }
        }

        return head;
    }
};
  • 时间复杂度为O(n)
  • 空间复杂度为O(1)

虚拟头节点法:

/**
 * 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 != NULL) {
            if(cur->next->val == val) {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            } else cur = cur->next;
        }

        return dummyhead->next;
    }
};
  • 时间复杂度为O(n)
  • 空间复杂度为O(1)

Leetcode 707.设计链表

题目链接:707.设计链表
解题思路:先通过结构体定义链表的结构,任何带有index参数的操作都必须检查是否越界; 用虚拟头节点操作会简单很多,并且思考cur是dummy还是dummy->next;

class MyLinkedList {
public:
    struct ListNode {
        int val;
        ListNode* next;
        ListNode(int x):val(x), next(nullptr) {}
    };

    MyLinkedList() {
        size = 0;
        dummy = new ListNode(0);
    }
    
    int get(int index) {
        if(index > (size - 1) || index < 0) return -1;
        ListNode* cur = dummy->next;
        while(index--) cur = cur->next;

        return cur->val;
    }
    
    void addAtHead(int val) {
        ListNode* newNode = new ListNode(val);
        
        newNode->next = dummy->next;
        dummy->next = newNode;
        size++;
    }
    
    void addAtTail(int val) {
        ListNode* newNode = new ListNode(val);
        ListNode* cur = dummy;

        while(cur->next != NULL) cur = cur->next;
        cur->next = newNode;
        size++;
    }
    
    void addAtIndex(int index, int val) {
        if(index < 0 || index > size) return ;

        ListNode* newNode = new ListNode(val);
        ListNode* cur = dummy;
        while(index--) cur = cur->next;

        newNode->next = cur->next;
        cur->next = newNode;
        size++;
    }
    
    void deleteAtIndex(int index) {
        if(index > (size - 1) || index < 0) return;

        ListNode* cur = dummy;
        while(index--) cur = cur->next;
        ListNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        tmp = nullptr;
        size--;
    }
private:
    int size;
    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);
 */
  • 时间复杂度为:涉及到index的操作为O(index),其他都为O(1)
  • 空间复杂度为:O(n)

Leetcode 206.反转链表

题目链接:206.反转链表
解题思路:使用双指针pre和cur,使得cur->next=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* reverseList(ListNode* head) {
        ListNode* pre = NULL;
        ListNode* cur = head;

        while(cur) {
            ListNode* tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

递归法:

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

    ListNode* reverseList(ListNode* head) {
        return reverse(head, NULL);
    }
};
  • 时间复杂度为O(n)
  • 空间复杂度为O(n) 递归使用到了n个栈
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值