1.合并两个有序链表
public NodeList mergeNodeList(NodeList node1,NodeList node2){
NodeList headfirst = new NodeList();
NodeList head = headfirst;
while(node1!=null||node2!=null){
if (node1!=null&&node2!=null) {
if (node1.value < node2.value) {
head.next = node1;
node1 = node1.next;
} else if (node1.value > node2.value) {
head.next = node2;
node2 = node2.next;
} else {
//这里代码的顺序不能写反
head.next = node1;
node1 = node1.next;
head = head.next;
head.next = node2;
node2 = node2.next;
//错误写法
// head.next = node1;
// head = head.next;
//这里直接让node1指向node2,导致node1 = node1.next;的结果是node2的链表
// head.next = node2;
// node1 = node1.next;
// node2 = node2.next;
}
head = head.next;
}else if (node2!=null){
head.next=node2;
node2=node2.next;
head=head.next;
}else{
head.next=node1;
node2=node1.next;
head=head.next;
}
}
return headfirst.next;
}
这种写法比较臃肿,我们可以把遍历到相同的情况与另外其他一种合并,一次判断只处理其中一个重复节点
public NodeList mergeNodeList(NodeList node1, NodeList node2) {
NodeList firstHead = new NodeList();
NodeList head = firstHead;
while (node1 != null && node2 != null) {
if (node1.value <= node2.value) {
head.next = node1;
node1 = node1.next;
} else {
head.next = node2;
node2 = node2.next;
}
head = head.next;
}
//只剩下一个链表,因为是有序链表不用排序,直接将剩下的链表的当前节点直接拼接在后面
head.next = node1 == null ? node2 : node1;
return firstHead.next;
}
2.合并K个有序链表
第一种两两合并
public NodeList mergeNodeLists(NodeList[] nodeLists) {
NodeList currentNode = null;
for (NodeList node : nodeLists) {
currentNode = this.mergeNodeList(currentNode, node);
}
return currentNode;
}
第二种利用二分思想合并
public NodeList mergeNodeLists(List<NodeList> nodeLists) {
List<NodeList> newList ;
int length = nodeLists.size();
while (length!=1){
newList = new ArrayList<>();
if (length%2==0){
for (int i = 0; i <= length/2-1; i++) {
newList.add(this.mergeNodeList(nodeLists.get(length/2-1-i),nodeLists.get(length/2+i)));
length = newList.size();
}
}else {
nodeLists.add(new NodeList());
for (int i = 0; i <= length/2-1; i++) {
newList.add(this.mergeNodeList(nodeLists.get(length/2-1-i),nodeLists.get(length/2+i)));
length = newList.size();
}
}
nodeLists = newList;
}
return nodeLists.get(0);
}
这个代码看起来不太美观,优化后的代码如下
public NodeList mergeNodeLists(List<NodeList> nodeLists) {
List<NodeList> newList;
int length = nodeLists.size();
while (length != 1) {
newList = new ArrayList<>();
for (int i = 0; i < length / 2; i++) {
newList.add(i, this.mergeNodeList(nodeLists.get(i), nodeLists.get(i + length / 2)));
}
//如果nodeLists的长度为奇数,把最后一个加入newList,下一次循环处理
if (length % 2 != 0) {
newList.add(nodeLists.get(length - 1));
}
length = newList.size();
nodeLists = newList;
}
return nodeLists.get(0);
}
3.一道无聊的好题
给你两个链表,它们包含的节点数分别为M和N,现在要把一个链表的第a,第b节点中间的节点全部截掉,把另外一个节点拼接进去
代码入下:
public NodeList mergeInBetween(NodeList node1,NodeList node2,int a,int b) {
NodeList headA = node1;
NodeList headB = node1;
NodeList lastNode = node2;
int indexA=0;
int indexB=0;
while(indexA!=a){
headA=headA.next;
indexA++;
}
while(indexB!=b){
headB=headB.next;
indexB++;
}
while(lastNode.next!=null){
lastNode=lastNode.next;
}
if (a<b){
lastNode.next=headB;
headA.next=node2;
}else {
lastNode.next=headA;
headB.next=node2;
}
return node1;
}
本章的有序链表学习完毕