合并两个有序链表
链表知识点
- 链表是一种物理存储单元上非连续、非顺序的存储结构,是一组数据项的集合,每个数据项都是节点的一部分,每个节点同时包含指向下一节点的链接。
- 无论是数组还是链表,都是使用计算机内存(物理内存由一个个大小相同的内存单元构成),然而两者对物理的使用上不一样:链表不一定是连续的内存空间,一般通过next指针来遍历查找。data为自定义的数据,next为下一节点的地址。
链表的基本操作
插入
考虑插入位置的前驱节点与后继节点,其他节点不受影响。
temp = 待插入位置的前驱节点.next
待插入位置的前驱节点.next = 待插入指针
待插入指针.next = temp
删除
将需要删除的节点的前驱指针的next指针修改为其下下个节点
待删除位置的前驱节点.next = 待删除位置的前驱节点.next.next
遍历
链表的遍历是cur = cur.next
当前指针 = 头指针
while 当前节点不为空{
print(当前节点)
当前指针 = 当前指针.next
}
for(ListNode cur = head; cur != null; cur = cur.next){
print(cur.val)
}
解决链表题型
链表的考点:
- 指针的修改:
最典型的就是链表反转:递归地反转相邻的两个节点(由于链表的递归性)
#反转一个子链表,并返回新的头与尾
def reverse(self, head: ListNode, tail: ListNode, terminal:ListNode){#head是需要反转的头节点,tail是需要反转的尾节点
cur = head
pre = None
while cur!=terminal:
#在反转前,记录下一个节点的信息
next = cur.next
#修改指针
cur.next = pre
#继续往下走
pre = cur
cur = next
#反转后的新的头尾节点返回
return tail, head
- 链表的拼接:
比如本题–合并有序链表
链表需要注意的地方
-
环:
- 判断链表中是否存在环以及环的位置
- 对链表操作后出现了环
如何避免环的出现:通过画图,将所有对指针的操作都反应在图中,能够有效的看出链表中是否构成了环
-
前后序(进行链表的反转)
前序遍历:
def dfs(head, pre):
if not head:
return pre
#留下联系方式(由于后面的都没有处理,因此可以通过head.next定位到下一个)
next = head.next
#主逻辑在进入后面节点的前面(由于前面的都已经处理好了,因此不会有环)
head.next = pre
dfs(head, None)
后续遍历:
def dfs(head):
if not head or not head.next:
return head
#不需要留联系方式,因为后序遍历后面的节点已经走过了
res = dfs(head.next)
#主逻辑在进入后面的节点的后面,也就是递归返回的过程会执行到
head.next.next = head
#置空。防止环的产生
head.next = None
return res
误区
本来想着将两个链表合并,然后sort不就完事了,结果发现没有那么简单。
这里主要考的是递归与链表。
python如何实现链表
新建一个链表
class Node:
'''
data:节点保存的数据
_next:保存下一个节点对象
'''
def __init__(self, data, pnext=None):
self.data = data
self._next = pnext
链表的常用方法:
LinkedList() #创建空链表
is_empty() #判单链表是否为空
append(data) #在尾部添加一个元素
iter() #遍历链表
insert(idx, value) #插入一个元素,参数为插入元素的索引和值
remove(idx) #移除1个元素
size() #返回链表的元素数
search(item) #查找链表某元素,返回为布尔值
解决
- 递归解法
当一个链表为空,另一个不为空时,可以直接返回不为0的链表,这时可以得到结果。
if not list1: return list2
if not list2: return list1
比较两个链表的指针指向的节点值的大小,递归操作将较小的节点与剩下节点的merge操作结果合并
if list1.val <= list2.val:
list1.next = self.mergeTwoLists(list1.next, list2)
return list1
else:
list2.next = self.mergeTwoLists(list1, list2.next)
return list2
- 迭代解法
定义一个空链表,用来放置节点:
root = ListNode(-1)
pre = root#当前节点
比较两个链表指针指向的节点值的大小,将较小的节点添加到新链表中
while list1 and list2:
if list1.val <= list2.val:
pre.next = list1
list1 = list1.next
else:
pre.next = list2
list2 = list2.next
pre = pre.next
两个链表中可能还有未合并元素:
if not list1: pre.next = list2
if not list2: pre.next = list1
参考:
【十分钟知识一览】Python数据结构之链表
合并两个有序链表(python)
LeetCode-21 合并两个有序链表—Python代码实现及详解
力扣加加