一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情。
前言
笔者除了大学时期选修过《算法设计与分析》和《数据结构》还是浑浑噩噩度过的(当时觉得和编程没多大关系),其他时间对算法接触也比较少,但是随着开发时间变长对一些底层代码/处理机制有所接触越发觉得算法的重要性,所以决定开始系统的学习(主要是刷力扣上的题目)和整理,也希望还没开始学习的人尽早开始。
系列文章收录《算法》专栏中。
问题描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:
输入:l1 = [], l2 = []
输出:[]
示例 3:
输入:l1 = [], l2 = [0]
输出:[0]
提示:
- 两个链表的节点数目范围是 [0, 50]
- -100 <= Node.val <= 100
- l1 和 l2 均按 非递减顺序 排列
剖析
两个链表已经排好序了,可以使用双指针进行遍历比较大小,小的插在前面大的插在后面。步骤如下:
- 创建一个头节点 head,赋值返回结果的当前移动指针resultCurrent。
- 如果list1和list2都是非空的,当前指针((从头开始遍历))指向的元素进行比较,小的作为resultCurrent的next节点。
- 移动第2步较小链上的指针,resultCurrent=resultCurrent.next。重复第二步,直到list1或者list2遍历结束了。
- 其中一个遍历结束后把还没遍历结束的拼接在resultCurrent后面。
算法复杂度:
- 时间复杂度:m和n分别为两个链表的长度,最差的情况是交叉进行,比如2->4->6和1->3->5。所以为O(m+n)。
- 空间复杂度:O(1)。
代码
public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
//创建一个头指针方便后面操作
ListNode head = new ListNode(-1);
//返回结果的链表当前位置
ListNode resultCurrent = head;
while (list1 != null && list2 != null) {
//小于等于就拼接list1的节点,大于就拼接list2
if (list1.val <= list2.val) {
resultCurrent.next = list1;
list1 = list1.next;
} else {
resultCurrent.next = list2;
list2 = list2.next;
}
resultCurrent = resultCurrent.next;
}
//最后可能存在还没遍历完的链表,所以拼接上
resultCurrent.next = list1 != null ? list1 : list2;
return head.next;
}