Leetcode刷题总结——链表

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

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

Leetcode刷题总结——链表_第1张图片

数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。

链表是通过指针域的指针链接在内存中各个节点。

所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。

学会自己构造一个链表

Leetcode刷题总结——链表_第2张图片

C++会默认生成一个构造函数,但是这个构造函数不会初始化任何成员变量

Leetcode刷题总结——链表_第3张图片

所以如果不定义构造函数使用默认构造函数的话,在初始化的时候就不能直接给变量赋值。

链表和数组的特性区别:

Leetcode刷题总结——链表_第4张图片

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

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

链表操作的两种方式:

  1. 直接使用原来的链表来进行操作。
  2. 设置一个虚拟头结点在进行操作。

一、移除链表元素

Leetcode刷题总结——链表_第5张图片

移除一个节点之后,没有手动在内存中删除这个节点,leetcode依然也是可以通过的,只不过,内存使用的空间大一些而已,但依然要养成手动清理内存的习惯。

Leetcode刷题总结——链表_第6张图片

二、设计链表

Leetcode刷题总结——链表_第7张图片

Leetcode刷题总结——链表_第8张图片

Leetcode刷题总结——链表_第9张图片

Leetcode刷题总结——链表_第10张图片

三、反转链表

Leetcode刷题总结——链表_第11张图片

双指针法:

Leetcode刷题总结——链表_第12张图片

 递归法:

从后往前递归

Leetcode刷题总结——链表_第13张图片从前往后递归(对应双指针法) 

Leetcode刷题总结——链表_第14张图片

返回值是一对链表的情况

Leetcode刷题总结——链表_第15张图片

四、两两交换链表中的节点

Leetcode刷题总结——链表_第16张图片

方法一:

Leetcode刷题总结——链表_第17张图片

 方法二:

Leetcode刷题总结——链表_第18张图片

 五、删除链表的倒数第N个节点

Leetcode刷题总结——链表_第19张图片

 方法一:先通过一次遍历得到链表的长度

Leetcode刷题总结——链表_第20张图片

 方法二:利用栈的先进后出性质

Leetcode刷题总结——链表_第21张图片

 方法三:利用快慢指针一次遍历,让快指针先走n步,最后当快指针走到链表尾部的时候,慢指针正好走到倒数第n个链表的前一个节点

Leetcode刷题总结——链表_第22张图片

 六、链表相交

Leetcode刷题总结——链表_第23张图片

 Leetcode刷题总结——链表_第24张图片

方法一:先分别求出两个链表的长度之差,然后先遍历长的链表,使得长短链表从同一起点处继续遍历

Leetcode刷题总结——链表_第25张图片

Leetcode刷题总结——链表_第26张图片

 方法二:

先遍历一条链表,并用一个set容器记录,再遍历另一条链表,看看有没有重复的节点

Leetcode刷题总结——链表_第27张图片

方法三:双指针法

参考链接

使用双指针的方法,可以将空间复杂度降至 O(1)。

只有当链表headA 和headB 都不为空时,两个链表才可能相交。因此首先判断链表 headA 和 headB 是否为空,如果其中至少有一个链表为空,则两个链表一定不相交,返回 null。

当链表 headA 和headB 都不为空时,创建两个指针tempA 和 tempB,初始时分别指向两个链表的头节点 headA 和 headB,然后将两个指针依次遍历两个链表的每个节点。具体做法如下:

每步操作需要同时更新指针tempA 和tempB。

如果指针 tempA不为空,则将指针 tempA 移到下一个节点;如果指针tempB 不为空,则将指针 tempB 移到下一个节点。

如果指针 tempA为空,则将指针tempA 移到链表 headB 的头节点;如果指针 tempB 为空,则将指针 tempB移到链表headA 的头节点。

当指针tempA 和 tempB 指向同一个节点或者都为空时,返回它们指向的节点或者 null。

证明

下面提供双指针方法的正确性证明。考虑两种情况,第一种情况是两个链表相交,第二种情况是两个链表不相交。

情况一:两个链表相交

链表headA 和 headB 的长度分别是 m 和 n。假设链表 headA 的不相交部分有 a 个节点,链表 headB 的不相交部分有 b 个节点,两个链表相交的部分有 c 个节点,则有 a+c=m,b+c=n。

如果a=b,则两个指针会同时到达两个链表相交的节点,此时返回相交的节点;

如果 a !=b 则指针 tempA 会遍历完链表 headA,指针 tempB 会遍历完链表 headB,两个指针不会同时到达链表的尾节点,然后指针tempA 移到链表 headB 的头节点,指针tempB 移到链表headA 的头节点,然后两个指针继续移动,在指针 tempA 移动了 a+c+b 次、指针 tempB 移动了 b+c+a 次之后,两个指针会同时到达两个链表相交的节点,该节点也是两个指针第一次同时指向的节点,此时返回相交的节点。

情况二:两个链表不相交

链表 headA 和headB 的长度分别是 m 和 n。考虑当 m=n 和 m!=n时,两个指针分别会如何移动:

如果m=n,则两个指针会同时到达两个链表的尾节点,然后同时变成空值 null,此时返回 null;

如果 m!=n ,则由于两个链表没有公共节点,两个指针也不会同时到达两个链表的尾节点,因此两个指针都会遍历完两个链表,在指针tempA移动了m+n 次、指针 tempB 移动了 n+m 次之后,两个指针会同时变成空值 null,此时返回 null。

Leetcode刷题总结——链表_第28张图片

七、环形链表

Leetcode刷题总结——链表_第29张图片

Leetcode刷题总结——链表_第30张图片

 方法一:空间复杂度O(n)Leetcode刷题总结——链表_第31张图片

 方法二:空间复杂度O(1)

利用快慢指针

解题思路

Leetcode刷题总结——链表_第32张图片

你可能感兴趣的:(C++刷题笔记,链表,leetcode,数据结构)