文章目录

前言链表什么是链表LeetCode 203. 移除链表元素LeetCode 707. 设计链表LeetCode 206. 反转链表

总结

前言

链表题公式解:链表转数组->操作数组->数组转链表 打卡第三天~ 今天是链表专题~

链表

什么是链表

今天将结束数组,开始链表的学习,那么对于链表,他的结构与特点相比较数组还是有很大的差距的;

什么是链表 链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针)。

链表的入口节点称为链表的头结点也就是head。

链表的内存管理 数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。 链表是通过指针域的指针链接在内存中各个节点。 所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。 如图所示

链表-链表与数据性能对比

数组在定义的时候,长度就是固定的,如果想改动数组的长度,就需要重新定义一个新的数组。

链表的长度可以是不固定的,并且可以动态增删, 适合数据量不固定,频繁增删,较少查询的场景。

接下来进入正题,刷题环节~

LeetCode 203. 移除链表元素

203. 移除链表元素 文章讲解 视频讲解 状态 : AC

看到这题,我首先想到了之前做的题目 LeetCode 27 移除元素 其区别只在于,一个是操作链表,一个是操作数组 那么是不是可以先将链表元素存入数组中,再操作数组,最后转换为链表呢 这就是链表题的一种通解

AC代码示例:

class Solution {

public:

ListNode* removeElements(ListNode* head, int s) {

ListNode *p=head;

vector nums;

// 一 将链表元素存入数组

while(p){

nums.push_back(p->val);

p=p->next;

}

// 二 对数组进行相应操作

int slow=-1,fast=0;

while(fast

if(slow

slow++;

nums[slow]=nums[fast];

}

fast++;

}

// 三 再转换为链表

if(slow+1>0)

head->val=nums[0];

else return nullptr;

head->next=nullptr;

p=head;

for(int i=1;i

ListNode *Next=new ListNode(nums[i]);

p->next=Next;

p=p->next;

}

return head;

}

};

时间复杂度:O(n)空间复杂度:O(n) (开辟数组空间)

LeetCode 707. 设计链表

LeetCode 707. 设计链表 文章讲解 视频讲解 状态 : Debug 半小时 终于A了

这一题就得老老实实的掌握链表了 题目还是不错的,一题涉及了链表的增删改(?)查 看见就上手一顿操作,然后报错www,主要是index下标的问题 最后慢慢debug才整出来,但原来的太丑了 再看卡哥的讲解…自己重新写了一份

AC代码示例:

class MyLinkedList {

struct myList{

int val;

myList* next;

myList():val(0),next(nullptr){}

myList(int a):val(a),next(nullptr){}

myList(int a, myList* next_a):val(a),next(next_a){}

};

public:

MyLinkedList(){

listhead=new myList(0);

list_size=0;

}

int get(int index) {

if(index>=list_size) return -1;

int count=0;

myList* pmove=listhead;

while(count != index){

count++;

pmove=pmove->next;

}

return pmove->val;

}

void addAtHead(int val) {

if(list_size==0){

myList* newnode=new myList(val);

listhead=newnode;

list_size++;

return;

}

myList* newnode=new myList(val);

newnode->next=listhead;

listhead=newnode;

list_size++;

}

void addAtTail(int val) {

if(list_size==0){

myList* newnode=new myList(val);

listhead=newnode;

list_size++;

return;

}

myList* pmove=listhead;

while(pmove->next){

pmove=pmove->next;

}

myList* newnode=new myList(val);

pmove->next=newnode;

list_size++;

}

void addAtIndex(int index, int val) {

if(index>list_size) return;

if(index==0){

addAtHead(val);

return;

}

int count=0;

myList* pmove=listhead;

while(count+1 != index){

count++;

pmove=pmove->next;

}

list_size++;

myList* newnode=new myList(val,pmove->next);

pmove->next=newnode;

}

void deleteAtIndex(int index) {

if(index>=list_size) return;

int count=0;

myList* pmove=listhead;

if(index==0){

listhead=listhead->next;

list_size--;

return;

}

while(count+1 != index){

count++;

pmove=pmove->next;

}

pmove->next=pmove->next->next;

list_size--;

}

int list_size;

myList* listhead;

};

时间复杂度: 涉及 index 的相关操作为 O(index), 其余为 O(1)空间复杂度: O(n)

LeetCode 206. 反转链表

LeetCode 206. 反转链表 文章讲解 视频讲解 状态 : 2分钟搞定

这题就能用公式搞定 链表转数组->操作数组->数组转链表 但建议还是手写一遍常规解,毕竟学习的是链表嘛!

AC代码示例(公式解):

class Solution {

public:

ListNode* reverseList(ListNode* head) {

ListNode *pmove=head;

vectornums;

//一. 链表转数组

while(pmove){

nums.push_back(pmove->val);

pmove=pmove->next;

}

//二. 操作数组

reverse(nums.begin(),nums.end());

//三. 数组转链表

if(nums.size()>0)

head->val=nums[0];

else return nullptr;

head->next=nullptr;

pmove=head;

for(int i=1;i

ListNode *Next=new ListNode(nums[i]);

pmove->next=Next;

pmove=pmove->next;

}

return head;

}

};

时间复杂度: O(n)空间复杂度: O(n) (开辟数组)

当然常规解也是要学习的~

AC代码示例(公式解):

class Solution {

public:

ListNode* reverseList(ListNode* head) {

ListNode* temp;

ListNode* cur = head;

ListNode* pre = NULL;

while(cur) {

temp = cur->next;

cur->next = pre;

pre = cur;

cur = temp;

}

return pre;

}

};

时间复杂度: O(n)空间复杂度: O(1)

总结

坚持 2024- 4-19

文章来源

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。