剑指 Offer(第2版)面试题 25:合并两个排序的链表
- 剑指 Offer(第2版)面试题 25:合并两个排序的链表
- 解法1:递归
- 解法2:迭代
剑指 Offer(第2版)面试题 25:合并两个排序的链表
题目来源:36. 合并两个排序的链表
解法1:递归
代码:
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution
{
public:ListNode *merge(ListNode *l1, ListNode *l2){// 特判if (l1 == nullptr)return l2;if (l2 == nullptr)return l1;ListNode *mergeHead = nullptr;if (l1->val <= l2->val){mergeHead = l1;mergeHead->next = merge(l1->next, l2);}else{mergeHead = l2;mergeHead->next = merge(l1, l2->next);}return mergeHead;}
};
复杂度分析:
时间复杂度:O(len1+len2),其中 len1 是链表 l1 的长度, len2 是链表 l2 的长度。因为每次调用递归都会去掉 l1 或者 l2 的头结点,(直到至少有一个链表为空),函数 merge 至多只会递归调用每个节点一次。因此,时间复杂度取决于合并后的链表长度,即 O(len1+len2)。
空间复杂度:O(len1+len2),其中 len1 是链表 l1 的长度, len2 是链表 l2 的长度。递归调用 merge 函数时需要消耗栈空间,栈空间的大小取决于递归调用的深度。结束递归调用时 merge 函数最多调用 len1+len2 次,因此空间复杂度为 O(len1+len2)。
解法2:迭代
设置两个指针 p1 和 p2 分别指向 l1 和 l2 的开头,模拟整个过程。
当一个指针为空时,说明已经遍历到了该链表的末尾,将另一个链表直接插入 merge 链表中即可。
代码:
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution
{
public:ListNode *merge(ListNode *l1, ListNode *l2){// 特判if (l1 == nullptr)return l2;if (l2 == nullptr)return l1;ListNode *dummy = new ListNode(-1);ListNode *cur = dummy;ListNode *p1 = l1, *p2 = l2;while (p1 && p2){if (p1->val <= p2->val){cur->next = p1;p1 = p1->next;}else{cur->next = p2;p2 = p2->next;}cur = cur->next;}if (p1 == nullptr)cur->next = p2;if (p2 == nullptr)cur->next = p1;return dummy->next;}
};
复杂度分析:
时间复杂度:O(len1+len2),其中 len1 是链表 l1 的长度, len2 是链表 l2 的长度。
空间复杂度:O(1)。