返回
剑指Offer之面试题25:有序链表合并,链上试炼!
后端
2024-01-06 14:09:11
大家好,我是热爱算法与数据结构的「螺旋君」,今天,我将带着大家一起探索剑指Offer之面试题25:有序链表合并。这是一道經典的面试题,也是数据结构与算法课程的常见考点。
题目背景:
假设我们有两个有序链表,其中一个链表包含[1, 3, 5],另一个链表包含[2, 4, 6]。现在,我们需要將这两个有序链表合并,最终输出一个包含所有元素的有序链表,即[1, 2, 3, 4, 5, 6]。
解題思路:
解题思路之一是采用递归的方法:
- 首先,比较两个链表的表头元素,较小的元素作为新链表的表头。
- 然后,将较小的元素从其链表中删除,并将剩下的链表作为递归调用时的参数。
- 重复步骤1和步骤2,直到两个链表都为空。
这种方法的优势是简洁明了,但在链表很长时,递归调用可能会导致堆栈溢出。因此,我们还可以考虑使用迭代的方法:
- 设置一个哨兵结点作为新链表的表头。
- 比较两个链表的表头元素,较小的元素作为新链表的表尾,较大的元素从其链表中删除。
- 将新链表的表尾指向较小的元素,并将较小的元素从其链表中删除。
- 重复步骤2和步骤3,直到两个链表都为空。
这种方法的优势是避免了递归调用,但需要额外创建一个哨兵结点。
代码实现:
def merge_two_sorted_lists(l1, l2):
"""
:param l1: 有序链表1
:param l2: 有序链表2
:return: 合并后的有序链表
"""
# 设置哨兵结点
dummy = ListNode(0)
# 当前结点指针
curr = dummy
# 循环比较两个链表的表头元素
while l1 and l2:
# 选择较小的元素作为新链表的表尾
if l1.val < l2.val:
curr.next = l1
l1 = l1.next
else:
curr.next = l2
l2 = l2.next
# 将当前结点指针移到下一个结点
curr = curr.next
# 将剩余的链表追加到新链表的尾部
if l1:
curr.next = l1
if l2:
curr.next = l2
# 返回哨兵结点的下一个结点,即新链表的表头
return dummy.next
复杂度分析:
- 时间复杂度:O(n + m),其中n和m分别为两个链表的长度。
- 空间复杂度:O(1),因为我们没有使用额外的空间来存储合并后的链表。
总结:
剑指Offer之面试题25:有序链表合并是一道经典的面试题,考察了算法和数据结构的基本功。通过这道题,我们可以更好地理解链表的基本操作,以及如何将两个有序链表合并成一个有序的新链表。