一、知识点介绍
1.单链表的逻辑结构与存储结构
逻辑结构:数据元素之间的逻辑关系 集合、线性结构(一对一)、树结构(一对多)、图结构(多对多)
存储结构:顺序存储、链式存储、索引存储、散列存储
2.单链表的定义
3.插入元素
4.删除元素
5.创建单链表
尾插法
头插法
上述2到5点均可分为两类代码的写法,需掌握:
带头结点的单链表(写代码方便)
不带头结点的单链表(写代码麻烦)
6.双链表
解决单链表逆向无法索引的问题
7.循环链表
循环单链表:从一个结点出发可以找到其他任何结点
循环双链表:从头找到尾和从尾找到头时间复杂度都是O(1)
二、例题
题目均来源于LeetCode题库
1.移除链表元素
思路:锁定前驱即可
# 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: ListNode, val: int) -> ListNode:
head=ListNode(next=head)
pre=head
while pre.next!=None:
if pre.next.val==val:
pre.next=pre.next.next
else:
pre=pre.next
return head.next
2.旋转链表
思路:使链表首尾相连,再利用链表长度和参数k来找到需要链表断开的位置
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head:
return None
length=0
tmp=head
while tmp.next:
length+=1
tmp=tmp.next
tmp.next=head
k=k%(length+1)
for i in range(length+1-k):
tmp=tmp.next
head=tmp.next
tmp.next=None
return head
3.合并两个有序链表
思路:先根据两个链表的头元素值来确定主链表,再将副链表每个元素依次从头比较(操作比较繁琐)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
if (not list1) and (not list2):
return None
if (not list1) and list2:
return list2
if (not list2) and list1:
return list1
if list1.val<=list2.val:
head=ListNode(next=list1)
tmp=ListNode(next=list2)
else:
head=ListNode(next=list2)
tmp=ListNode(next=list1)
h=head
while tmp.next and h.next:
if h.next.val<tmp.next.val:
h=h.next
else:
t1=h.next
h.next=tmp.next
t2=tmp.next.next
tmp.next.next=t1
tmp.next=t2
if tmp.next:
h.next=tmp.next
return head.next
4…链表相交
思路:先算出两个链表的长度,用长度差使得长链表和短链表在同一起跑线开始往后挪动,挪动过程中不断判断即可
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
if (not headA) or (not headB):
return None
tmpA=ListNode(next=headA)
tmpB=ListNode(next=headB)
lenA=0
lenB=0
while tmpA.next:
lenA+=1
tmpA.next=tmpA.next.next
while tmpB.next:
lenB+=1
tmpB.next=tmpB.next.next
if lenA<=lenB:
while lenA!=lenB:
lenB-=1
headB=headB.next
else:
while lenA!=lenB:
lenA-=1
headA=headA.next
while headA and headB:
if headA==headB:
return headA
else:
headA=headA.next
headB=headB.next
return headA
5.删除排序链表中的重复元素II
思路:使用一个前驱指针和临时指针,两种指针中间需要隔开,并用一个变量(本人命名为last)存储中间元素的值;不断比较临时指针所指向的元素的值和last值并移动临时指针,当临时指针绝对安全时使前驱指针往后移动一个单位。(稍微有点抽象,直接看代码吧)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if not head:
return None
head=ListNode(val=-999,next=head)
last=head.val
tmp=head.next
pre=ListNode(next=head)
while tmp:
if last==tmp.val:
while tmp.val==last:
tmp=tmp.next
if not tmp:
pre.next=None
return head.next
pre.next=tmp
last=tmp.val
tmp=tmp.next
else:
pre=pre.next
last=tmp.val
tmp=tmp.next
return head.next