引言:以下内容均只是个人看法,并无严格经过核对,如有异议,欢迎交流,发现错误,欢迎您的及时指正,感谢!本文所示代码均为java代码
本文中使用的结点定义语句如下
public class listNode {
public int data;
public listNode next;
public listNode(int data) {
this.data = data;
this.next=null;
}
}
单链表的遍历一般从第一个结点依次遍历整个链表,所以第一个结点十分重要,在本文中头节点指的是第一个存放数据的结点,与其他相关文章中关于它的定义可能不同,无需深究,理解相关操作的逻辑原理即可,本质上无较大差别。
1.合并两个有序链表
两个链表均有序,所以在合并时,两个链表均从头开始遍历,然后比较两个链表的当前元素,较小的插入新的链表,同时对应链表的指针后移,比较到其中一个链表为空,就把非空链表的剩下的结点直接连到新建链表的后面,对于其中的一些特殊情况我们采用试着化特殊为一般的方法,比如当有两个结点的数据相等时需要单独写一个if判断吗?
我们举例说明如何解决现有list1(1-2-3-4)和list2(2-5-6)两条链表,首先我们判断两个链表的第一个结点1<2,1放入新建的链表,同时对应指针后移,现在两个链表比较的结点的数据均为2,我们在代码中将等于的情况并入list1<=list2,此时符合条件,list1此时指向的2并入新链表,然后list1指向3,此时list2指向的2小于3,所以list2中的2也并入新链表,即实现了相等情况的判断
基本实现如下图
/**
* 0
* @param list1 要合并的有序链表1
* @param list2 要合并的有序链表2
* @return
*/
public listNode mergeTwoLists(listNode list1, listNode list2) {
//新建的链表的虚拟结点,它的next才是第一个结点
listNode newList=new listNode();
listNode prev=newList;
//prev作为实时指针进行新建链表的插入操作 尾插法
//插入操作每次插入的时两个链表元素比较较小的元素
while(list1!=null&&list2!=null){
if(list1.data<=list2.data){
prev.next=list1;
list1=list1.next;
prev=prev.next;
}else{
prev.next=list2;
list2=list2.next;
prev=prev.next;
}
}
//如果有一个链表为空,直接把另一个链表加到newList之后
prev.next=(list1==null)?list2:list1;
return newList.next;
}
2.合并K个链表
合并k个链表,有多种方式,比如堆,归并,我们在这里对于面试更倾向于先将前两个合并,再将后面的合并起来,因为这样前两个写清楚后面的合并k个就比较容易。目前仅阐述这一种方法,后面再做补充。前提每个链表都是非递减的,代码如下:
其中mergeTwoLists是上面的代码
/**
*
* @param lists 要合并的链表的头结点的数组
* @return
*/
//合并k个有序链表
public ListNode mergeKLists(ListNode[] lists) {
ListNode res = null;
for (ListNode list: lists) {
res = mergeTwoLists(res, list);
}
return res;
}
3.一道很无聊的好题
leetcode1669,现有list1,list2两条链表,把list1中的下标从a开始到b的节点全部删除,然后把list2插入list1中空缺的位置,链表的第一个节点下标是0
/**
*
* @param list1 第一个链表
* @param a 删除节点的起始下标
* @param b 删除节点的终点下标
* @param list2 第二个链表
* @return
*/
//leetcode1669,现有list1,list2两条链表,把list1中的下标从a开始到b的节点全部删除,然后把list2插入list1中空缺的位置
public listNode mergeInBetween(listNode list1, int a, int b, listNode list2) {
listNode node=list1;//遍历list1找到进行指针操作的两个结点
listNode node_a=null,node_b=null;
listNode node2=list2;//遍历list2找到list2的尾节点
int index=0;
int remove=0;
while(node!=null){
if(index==a-1){
node_a=node;
}
if(index==b+1){
node_b=node;
}
node=node.next;
index++;
}
//让第二个链表的尾节点连接第一个链表下标b后面的节点
node_a.next=list2;
while(node2.next!=null){
node2=node2.next;
}
node2.next=node_b;
return list1;
}