本次写的题目是链表分割,为牛客网里面的题目,让我们来康康是如何解出这道题目的吧,各位尚没有思路的小伙伴可以跟随着博主的解题思路一步步来,感受一下😎
🌱分析阶段
初读题目,要求是在不改变原来的顺序下,将链表中小于某个值的结点挑出来组成一个链表之后拼回被挑出来的数组前。图示如下👇
从该图中我们可以看出要解此题,需要用到两个链表,一个链表放入小于要求数的,另一个链表放入大于或等于要求数的,然后要在这两个链表中补充新结点进去,为了不打乱顺序,所以使用到尾插法,然后设置四个结点,分别为bs、be、as、ae,用于两个链表的创建,如下图👇:
在创建完这两个链表后,将这两个链表链接到一起即可,也就是让图中的be.next放入as的引用。
以上便是解出该题的大致思路,下面来到具体的代码部分😎
🌱代码阶段
本题在代码部分细节较多,我们来一一分析。
在大致思路完成后进入到写代码阶段的时候,我们要首先想到下面的几种特殊情况:①当该链表为空链表的时候;②创建两个链表,要怎么开始创建;③创建了两个链表,若该链表中的每个元素都大于指定数怎么处理?都小于指定数怎么处理?
目前大致想出粗略的三个特殊情况,先解决特殊情况①👇:
public class Partition {
public ListNode partition(ListNode pHead, int x) {
if(pHead==null) return null; //当该链表为空链表的时候,直接返回null
}
}
然后就到了创建两个链表的时候,要创建两个链表,我们需要用到一前一后两个结点,一个作为头结点,另一个作为尾结点。所以,小于指定数的链表的头结点命名为bs(before start)、尾结点命名为be(before end);大于或等于指定数的链表的头结点命名为as(after start)、尾结点命名为ae(after end)。
在这里bs、be、as、ae都先设置为null。
public class Partition {
public ListNode partition(ListNode pHead, int x) {
if(pHead==null) return null;
ListNode cur = pHead; //用于遍历一遍链表与指定值x对比
ListNode bs = null;
ListNode be = null;
ListNode as = null;
ListNode ae = null;
}
之后就是遍历链表比较,将链表内的结点分类放入两个链表中,其中需要注意的是要区分是不是第一次放入结点,具体代码如下👇:
public class Partition {
public ListNode partition(ListNode pHead, int x) {
if(pHead==null) return null;
ListNode cur = pHead;
ListNode bs = null;
ListNode be = null;
ListNode as = null;
ListNode ae = null;
while(cur!=null){
if(cur.val<x){
if(bs==null){ //如果bs还是null,说明是第一次放入该链表,所以要创建一个链表
bs = new ListNode(cur.val);
be = bs;
}else{
be.next = cur;
be = be.next;
}
}else{
if(as==null){
as = new ListNode(cur.val);
ae = as;
}else{
ae.next = cur;
ae = ae.next;
}
}
cur = cur.next;
}
}
}
至此,分完类后我们需要判断并解决特殊情况③:创建了两个链表,若该链表中的每个元素都大于指定数怎么处理?都小于指定数怎么处理?具体解决部分看下面的代码👇:
public class Partition {
public ListNode partition(ListNode pHead, int x) {
if(pHead==null) return null;
ListNode cur = pHead;
ListNode bs = null;
ListNode be = null;
ListNode as = null;
ListNode ae = null;
while(cur!=null){
if(cur.val<x){
if(bs==null){
bs = new ListNode(cur.val);
be = bs;
}else{
be.next = cur;
be = be.next;
}
}else{
if(as==null){
as = new ListNode(cur.val);
ae = as;
}else{
ae.next = cur;
ae = ae.next;
}
}
cur = cur.next;
}
if(as == null){ //判断这个是当链表中没有小于x的结点值 //这个必须得判断,不然后面会报错,会空指针异常
return bs;
}
if(bs==null){ //这个是当链表中没有大于或等于x的结点值
return pHead;
}
}
}
之后就是将两个链表连接起来,这一步很简单,但是写到此时还没有结束,本题还有一个小细节:将ae.next设置为null。这是因为由于ae是从原链表中拿来的,其next域可能还保留这原来的引用,如果没有设置为null,可能会导致有环形链表出现,最后导致死循环。所以最终的代码如下👇:
public class Partition {
public ListNode partition(ListNode pHead, int x) {
if(pHead==null) return null;
ListNode cur = pHead;
ListNode bs = null;
ListNode be = null;
ListNode as = null;
ListNode ae = null;
while(cur!=null){
if(cur.val<x){
if(bs==null){
bs = new ListNode(cur.val);
be = bs;
}else{
be.next = cur;
be = be.next;
}
}else{
if(as==null){
as = new ListNode(cur.val);
ae = as;
}else{
ae.next = cur;
ae = ae.next;
}
}
cur = cur.next;
}
if(as == null){ //这个必须得判断,不然后面会报错,会空指针异常
return bs;
}
if(bs==null){
return pHead;
}
ae.next = null; //在这里要记得将最后结点的next给null,不然很有可能变成循环链表,就进入死循环了
be.next = as;
pHead = bs;
return pHead;
}
}
以上,便是全部代码了😎运行一下逝逝吧
nice~😎✨