两个有序数组,合并为一个链表,并且合并后仍然有序
自定义链表结构如下
public class Node {
Node head;
Node next;
Integer val;
public Node (Integer node){
val = node;
}
public static void list(Node node){
Node next = node;
while (next != null){
System.out.println(next.val);
next = next.next;
}
}
public static Node create (Integer ... nums){
Node head = new Node(0);
Node next = head;
for (Integer num : nums) {
next.next = new Node(num);
next = next.next;
}
return head.next;
};
}
以上是自定义的node,用来创建链表和输出链表
private static Node merge2List(Node e1, Node e2) {
//任何一个链表为null,直接输出另一个链表
if (e1 == null || e2 == null) {
return e1 == null ? e2 : e1;
}
//创建一个新的head节点来输出结果,并把tail指向head
Node head = new Node(0);
Node tail = head, a = e1, b = e2;
while (a != null && b != null) {
//比较两个链表的第一个元素,较小的放入结尾tail.next
if (a.val < b.val) {
tail.next = a;
a = a.next;
} else {
tail.next = b;
b = b.next;
}
//tail后移
tail = tail.next;
}
//任意一个链表遍历完毕,直接把另一个链表接入尾部
tail.next = a == null ? b : a;
return head.next;
}
解决思路
- 任何一个链表为null,直接输出另一个链表
- 创建一个新的head节点来输出结果,并把tail指向head
- 每次遍历比较两个链表的第一个元素,较小的放入结尾tail.next并tail后移
- 任意一个链表遍历完毕,直接把另一个链表接入尾部
进阶 多个有序数链表并为一个有序链表
容易想到使用二分法来进行分治,两两合并,直至合并为一个链表为止
private static Node merge(List<Node> list, int left, int right) {
//合并到最后一个链表,直接返回
if (left == right) {
return list.get(left);
}
//校验参数合法
if (left > right) {
return null;
}
//merge递归合并左右部分,最后等价于合并两个有序链表merge2List
int mid = (left + right) / 2;
return merge2List(merge(list, left, mid), merge(list, mid + 1, right));
}
测试
public static void main(String[] args) {
Node list1 = Node.create(1, 2, 3, 4, 5);
Node list2 = Node.create(1, 2, 5, 6, 6);
Node list3 = Node.create(2, 2, 5, 7, 9);
List<Node> list = new ArrayList<>();
list.add(list1);
list.add(list2);
list.add(list3);
Node head = merge(list, 0, list.size() - 1);
head.list(head);
}