您的位置:首页 > 其它

合并K个有序链表

2017-10-17 16:40 253 查看

1.利用堆的特性

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;

class Node {
public Integer value;
public Node next;// 指向下一个节点
public Node(int value) {
this.value=value;
}
}

public class KSortedLinkedList {
static PriorityQueue<Node> queue = new PriorityQueue<Node>(new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
return o1.value -o2.value;
}
});

public static void just(LinkedList<Node> list) {
if (list != null && list.size() != 0) {
for (int i = 0; i < list.size() - 1; i++) {
list.get(i).next = list.get(i + 1);
}
list.get(list.size() - 1).next = null;
}
}

public static void sort(LinkedList<Node>[] kList) {
ArrayList<Integer> newList = new ArrayList<Integer>();
//首先将k个LinkedList的每个header部分放到queue中
for (LinkedList<Node> list : kList) {
if (list.isEmpty() == false)
queue.offer(list.pop());
}
while (queue.isEmpty() == false) {
Node node=queue.poll();
newList.add(node.value);
//将node的下一个节点添加到queue中
if(node.next != null) {
queue.add(node.next);
}
}
for (int n : newList) {
System.out.print(n + "   ");
}
}

public static void main(String[] args) {
LinkedList<Node>[] kList = new LinkedList[4];
kList[0] = new LinkedList<Node>();
kList[1] = new LinkedList<Node>();
kList[2] = new LinkedList<Node>();
kList[3] = new LinkedList<Node>();
kList[0].add(new Node(-11));
kList[0].add(new Node(-3));
kList[0].add(new Node(5));
kList[0].add(new Node(7));
kList[1].add(new Node(2));
kList[1].add(new Node(14));
kList[1].add(new Node(16));
kList[1].add(new Node(28));
kList[2].add(new Node(28));
kList[2].add(new Node(29));
kList[2].add(new Node(30));
kList[3].add(new Node(29));
kList[3].add(new Node(52));
just(kList[0]);
just(kList[1]);
just(kList[2]);
just(kList[3]);
sort(kList);
}
}


如果K个排序的LinkedList中的元素是按照大小逆序排序的,只需要将compare改为o2.value -o1.value.

关键点分析:

PriorityQueue是一个堆,默认是最小堆。

An unbounded priority {@linkplain Queue queue} based on a priority heap.

首先将k个已经排序的LinkedList的header放到最小堆中,然后取出堆顶的元素,即最小的元素,再把刚取出元素的后面一个元素放到堆中,以此类推循环。这里,使用“指针”的方式,很便捷,假设不用这种指针方式,还真不好处理。

2.分治算法

import java.util.LinkedList;

public class KSortedLinkedList2 {

public static LinkedList<Integer> mergeK(LinkedList<Integer>[] listArr,int low,int high){
if(low==high) return listArr[low];
if(high-low==1) return merge2(listArr[low],listArr[high]);
int mid=(low+high) / 2;
LinkedList<Integer> list1=mergeK(listArr,low,mid);
LinkedList<Integer> list2=mergeK(listArr,mid+1,high);
return merge2(list1,list2);
}

public static LinkedList<Integer> merge2(LinkedList<Integer> list1 , LinkedList<Integer> list2) {
LinkedList<Integer> newList=new LinkedList<Integer>();
int i=0,j=0;
for(;i<list1.size() && j<list2.size();) {
if(list1.get(i)<=list2.get(j)) {
newList.add(list1.get(i));
i++;
}else {
newList.add(list2.get(j));
j++;
}
}
if(i<list1.size()) {
while(i<list1.size()) {
newList.add(list1.get(i));
i++;
}
}
if(j<list2.size()) {
while(j<list2.size()) {
newList.add(list2.get(j));
j++;
}
}
return newList;
}

public static void main(String[] args) {
LinkedList<Integer> list1=new LinkedList<Integer>();
list1.add(1);
list1.add(3);
list1.add(7);
list1.add(10);
list1.add(16);
LinkedList<Integer> list2=new LinkedList<Integer>();
list2.add(0);
list2.add(4);
list2.add(9);
LinkedList<Integer> list3=new LinkedList<Integer>();
list3.add(2);
list3.add(6);
list3.add(21);
LinkedList<Integer> list4=new LinkedList<Integer>();
list4.add(-2);
list4.add(12);
list4.add(22);
LinkedList<Integer>[] listArr=new LinkedList[4];
listArr[0]=list1;
listArr[1]=list2;
listArr[2]=list3;
listArr[3]=list4;
LinkedList<Integer> newList=mergeK(listArr,0,listArr.length-1);
for (int n : newList) {
System.out.print(n + "   ");
}
}

}


参考链接:

http://blog.csdn.net/mine_song/article/details/69501383

https://www.2cto.com/kf/201606/514246.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: