1. 题目
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。例如,输入图中的链表1和链表2,则合并之后的升序链表如链表3所示。链表节点定义如下:
2. 解题思路
很明显,需要两个指针,一个指针遍历链表1,一个指针遍历链表2,然后在遍历的过程中比较这两个节点的大小,小的节点就作为剩余未合并的两个链表在合并后的头节点,然后重复这一过程。那么也就是说递归是能够实现这个功能的。
3. 代码实现
3.1 递归版
一定要注意递归的基线条件。
# 递归版
def merge_list(head1, head2):
# 一个链表为None, 则直接返回另一个,递归的基线条件
if not head1:
return head2
if not head2:
return head1
# head1和head2都不为None
p1 = head1 # 指针1
p2 = head2 # 指针2
merge_head = None # 指针3,剩余链表合并之后的头节点
if p1.value > p2.value:
merge_head = p2
merge_head.next = merge_list(p1, p2.next)
else:
merge_head = p1
merge_head.next = merge_list(p1.next, p2)
return merge_head
3.1 循环版
在循环版本中,使用了多个指针,前两个指针分别指向需要合并的链表,第3个指针指向合并后的链表头节点(最后返回的就是这个指针),第4个指针指向合并后链表的最后一个节点,根据两个链表中剩余节点的大小来决定第4个指针指向哪一个节点。
# 非递归版
def merge_list2(head1, head2):
"""
循环,都是原地修改
"""
# 一个链表为None, 则直接返回另一个
if not head1:
return head2
if not head2:
return head1
# head1和head2都不为None
p1 = head1 # 指针1
p2 = head2 # 指针2
merge_head = None # 指针3,剩余链表合并之后的头节点
if head1.value > head2.value:
merge_head = head2
p2 = head2.next
else:
merge_head = head1
p1 = head1.next
merge_next = merge_head # 指针4,指向合并后链表的最后一个节点
while p1 != None and p2 != None:
if p1.value > p2.value: # 若p1的值大于p2的值,则merge_next指向当前的p2,merge_next后移一位,p2后移一位
merge_next.next = p2
merge_next = merge_next.next
p2 = p2.next
else: # 若p2的值大于p1的值,则merge_next指向当前的p1,merge_next后移一位,p1后移一位
merge_next.next = p1
merge_next = merge_next.next
p1 = p1.next
# 当两个链表长度不同时,直接指向长的链表的剩余的头节点即可
if p1 == None:
merge_next.next = p2
if p2 == None:
merge_next.next = p1
return merge_head
4. 总结
始终记住链表的操作始终是围绕指针的,提高效率可能就会使用到多个指针。一般都是这几种:
1.两个指针,同时同步移动
2.两个指针相隔一定距离同步移动
3.两个指针以不同的速率移动(链表中环)
5. 参考文献
[1] 剑指offer丛书