大厂面试手撕面试题:合并两个有序链表(亲测可用的java实现)
在面试中,合并两个有序链表的题目是非常常见的。这个问题的关键是利用两个链表的有序性来高效地合并它们。
思路:
- 初始化两个指针:
- 一个指针指向链表A的头节点,另一个指针指向链表B的头节点。
- 比较两个指针所指向的节点值:
- 比较当前两个节点的值,将较小的节点添加到新的链表中。
- 然后,移动对应指针到下一个节点,继续比较。
- 处理剩余的部分:
- 当其中一个链表的节点全部合并到新链表后,直接将另一个链表的剩余部分连接到新链表上。
- 返回结果:
- 合并完成后返回新链表的头节点。
时间复杂度:
- 每个链表的节点都需要访问一次,时间复杂度为 �(�+�)O(n+m),其中 �n 和 �m 分别是两个链表的长度。
空间复杂度:
- 空间复杂度为 �(1)O(1),因为我们是在原地合并链表,没有使用额外的空间(除了新链表的头节点指针)。
Java代码实现:
// Definition for singly-linked list.
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
// 创建一个虚拟头节点,简化处理
ListNode dummy = new ListNode(0);
ListNode current = dummy;
// 遍历两个链表
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
current.next = l1;
l1 = l1.next;
} else {
current.next = l2;
l2 = l2.next;
}
current = current.next;
}
// 如果有一个链表还剩余节点,直接连接到合并链表的尾部
if (l1 != null) {
current.next = l1;
} else if (l2 != null) {
current.next = l2;
}
// 返回合并后的链表,跳过虚拟头节点
return dummy.next;
}
}
代码解析:
- ListNode类: 这是链表节点的定义,每个节点包含一个整数值和一个指向下一个节点的指针。
- mergeTwoLists方法:
dummy
是一个虚拟的头节点,它用于简化处理过程,最终返回合并后的链表。current
用来追踪合并链表的最后一个节点。- 在 while 循环中,比较
l1
和l2
的当前节点,选择较小的节点并将其加入到合并链表中。然后,继续移动指针。 - 当一个链表结束时,直接将另一个链表剩余的部分连接到合并链表。
- 返回结果:
最后返回
dummy.next
,这是合并后的链表的头节点。