提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
链表理论
什么是链表,链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
链表的入口节点称为链表的头结点也就是head。
如图所示:
链表的类型:
(1)单链表
单链表的指针域只能指向节点的下一个节点
(2)双链表
节点有两个指针,一个指向上一个节点,另外一个指向下一个节点
(3)循环链表
链表收尾相连
链表操作的两种方式:
- 直接使用原来的链表来进行操作。
- 设置一个虚拟头结点在进行操作。
一、移除链表元素
通过设置一个虚拟头节点来移除其中某个节点
from typing import Optional
# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
p = ListNode(next=head)
cur = p
while cur.next != None:
if cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return p.next
二、设计链表
这道题目设计链表的五个接口:
- 获取链表第index个节点的数值
- 在链表的最前面插入一个节点
- 在链表的最后面插入一个节点
- 在链表第index个节点前面插入一个节点
- 删除链表的第index个节点
class Node:
def __init__(self,val):
self.val = val
self.next = None
class MyLinkedList:
def __init__(self,val=0,next=None):
self._head = Node(0)
self._count = 0
def get(self, index: int) -> int:
if 0<=index<self._count:
cur = self._head
for _ in range(index+1):
cur = cur.next
return cur.val
return -1
def addAtHead(self, val: int) -> None:
self.addAtIndex(0,val)
def addAtTail(self, val: int) -> None:
self.addAtIndex(self._count,val)
def addAtIndex(self, index: int, val: int) -> None:
if index<0:
index = 0
if index>self._count:
return
insert_node = Node(val)
self._count += 1
cur = self._head
for _ in range(index):
cur = cur.next
next_node = cur.next
insert_node.next = next_node
cur.next = insert_node
def deleteAtIndex(self, index: int) -> None:
if 0<=index<self._count:
prev_node=None
cur = self._head
self._count -= 1
for _ in range(index+1):
prev_node = cur
cur = cur.next
prev_node.next = cur.next
cur.next = None
三、链表反转
首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。
然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。
接下来,就是循环走如下代码逻辑了,继续移动pre和cur指针。
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev = None
cur = head
while cur is not None:
tmp = cur.next
cur.next = prev
prev = cur
cur = tmp
return prev
四、24.两两交换链表中的节点
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy_head = ListNode(0)
dummy_head.next = head
cur = dummy_head
while cur.next != None and cur.next.next != None:
tmp1 = cur.next.next # 指向第二个节点
tmp2 = cur.next # 指向第一个节点
tmp3 = cur.next.next.next # 指向第三个节点
cur.next = tmp1 # 交换第一,第二个节点的值
tmp1.next = tmp2
tmp2.next = tmp3
cur = cur.next.next # 前进2个节点
return dummy_head.next
五、19.删除链表的倒数第N个节点
- 定义虚拟头节点
- 定义fast指针和slow指针,初始值为虚拟头节点
- fast 首先走n+1步,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图:
- 删除slow指向的下一个节点,如图:
from typing import Optional
# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy_head = ListNode(0,next=head)
slow = dummy_head
fast= head
i= 0
while fast:
i += 1
fast = fast.next
if i>=n+1:
slow = slow.next
slow.next = slow.next.next
return dummy_head.next
六、160.链表相交
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
curA = headA
curB = headB
lenB = 0
lenA = 0
while curA:
curA = curA.next
lenA +=1
while curB:
curB = curB.next
lenB += 1
if lenA>lenB:
fastNode = headA
slowNode = headB
else:
fastNode = headB
slowNode = headA
diff = abs(lenB-lenA)
for i in range(diff):
fastNode = fastNode.next
while fastNode and slowNode:
if fastNode == slowNode:
return fastNode
fastNode = fastNode.next
slowNode = slowNode.next
七、142.环形链表II
题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
from typing import Optional
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
p = head
while p != slow:
p = p.next
slow = slow.next
return p
return None