描述
合并 k 個排序鏈表拴清,返回合并后的排序鏈表。
輸入:
[
1->4->5,
1->3->4,
2->6
]
輸出: 1->1->2->3->4->4->5->6
解題思路
1.將所有節(jié)點添加到數(shù)組中会通,對數(shù)組節(jié)點從小到大排序口予,依次取出每個節(jié)點串成鏈表。
// 時間復(fù)雜度:O(n*logn)涕侈,空間復(fù)雜度:O(n)沪停。
public ListNode mergeKLists(ListNode[] lists)
{
if (lists == null || lists.length == 0) return null;
List<ListNode> nodes = new ArrayList<ListNode>();
for (ListNode list : lists) {
while (list != null) {
nodes.add(list);
list = list.next;
}
}
nodes.sort((ListNode node1, ListNode node2) -> {
return node1.val - node2.val;
});
ListNode head = new ListNode(0);
ListNode cur = head;
for (ListNode node : nodes) {
cur = cur.next = node;
}
return head.next;
}
2.遍歷取出鏈表數(shù)組第一個節(jié)點,取最小的節(jié)點裳涛,然后串起來木张。
// 時間復(fù)雜度:O(k*n)
public ListNode mergeKLists(ListNode[] lists)
{
if (lists == null || lists.length == 0) return null;
ListNode head = new ListNode(0);
ListNode cur = head;
while (true) {
int minIndex = -1;//記錄最小值的索引
for (int i = 0; i < lists.length; i++) {
//某條鏈表已經(jīng)取完
if (lists[i] == null) continue;
//比較小的賦值
if (minIndex == -1 || lists[i].val < lists[minIndex].val) {
minIndex = i;
}
}
//取出了鏈表數(shù)組所有的值
if (minIndex == -1) break;
//串起來節(jié)點
cur = cur.next = lists[minIndex];
//取出后下移
lists[minIndex] = lists[minIndex].next;
}
return head.next;
}
3.利用Java數(shù)據(jù)結(jié)構(gòu)小頂堆。
// 時間復(fù)雜度:O(n*logk)端三,空間復(fù)雜度:O(k)舷礼。
public ListNode mergeKLists(ListNode[] lists)
{
if (lists == null || lists.length == 0) return null;
ListNode head = new ListNode(0);
ListNode cur = head;
PriorityQueue<ListNode> queue = new PriorityQueue<>((ListNode node1, ListNode node2) -> {
return node1.val - node2.val;
});
for (ListNode list : lists) {
if (list == null) continue;
queue.offer(list);
}
while (!queue.isEmpty()) {
ListNode list = queue.poll();
cur = cur.next = list;
if (list.next != null) {
queue.offer(list.next);
}
}
return head.next;
}
4.分治策略,將鏈表兩兩合并成一條郊闯,最后第一條鏈表就是結(jié)果妻献。
合并兩條鏈表
a、迭代
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
//虛擬頭結(jié)點
ListNode head;
//賦值頭結(jié)點
if (l1.val <= l2.val) {
head = l1;
l1 = l1.next;
} else {
head = l2;
l2 = l2.next;
}
ListNode cur = head;
//串起來剩余節(jié)點
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
cur = cur.next = l1;
l1 = l1.next;
} else {
cur = cur.next = l2;
l2 = l2.next;
}
}
//串完一個鏈表团赁,剩下的鏈表直接串后面即可
if (l1 == null) {
cur.next = l2;
} else if (l2 == null) {
cur.next = l1;
}
return head;
}
b旋奢、遞歸
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val <= l2.val) {
l1.next = mergeTwoLists2(l1.next,l2);
return l1;
} else {
l2.next = mergeTwoLists2(l1,l2.next);
return l2;
}
}
分治代碼
// 時間復(fù)雜度:O(n*logk)
public ListNode mergeKLists(ListNode[] lists)
{
if (lists == null || lists.length == 0) return null;
int step = 1;
while (step < lists.length) {
int nextStep = step << 1;// step*2
// 相鄰2、4然痊、8...
for (int i = 0; i+step < lists.length; i += nextStep) {
lists[i] = mergeTwoLists(lists[i], lists[i+step]);// 合并2條鏈表
}
step = nextStep;
}
return lists[0];
}