链表的荷兰国旗实现

68 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

给定一个链表,给定一个值num

让链表分区成三个部分,前面是小于num的,中间是等于num的,后面是大于num的。

思路

这个题目我们需要知道分区的根本是什么,是不是让一个链表变成了三个部分,或许有人会认为我这是废话文学,你往后看就知道了。

我们分成三个部分,就是三个小链表,定义6个变量

小于区域的头: shead

小于区域的尾: stail

等于区域的头: ehead

等于区域的尾: etail

大于区域的头: bhead

大于区域的尾: btail

然后我们开始遍历链表,拿到一个元素之后就看看它是哪个区域的,然后就把它放到它应该在的地方,最后把它们连起来就可以,就很简单了。我们直接看代码

代码

public static Node listPartition(Node head, int num){
    Node sHead = null;
    Node sTail = null;
    Node eHead = null;
    Node eTail = null;
    Node bHead = null;
    Node bTail = null;
    Node cur = head;
    //注意点1:我们需要一个next来记录下一个位置,为什么又这个操作呢?下面我会解答
    Node next = null;
    while(cur != null){
        next = cur.next;
        cur.next = null;
        if(cur.value < num){
            if(sHead == null){
                sHead = cur;
                sTail =cur;
            }else{
                sTail.next = cur;
                sTail = sTail.next;
            }
        }else if(cur.value == num){
            if(eHead == null){
                eHead = cur;
                eTail =cur;
            }else{
                eTail.next = cur;
                eTail = eTail.next;
            }
        }else if(cur.value > num){
            if(bHead == null){
                bHead = cur;
                bTail =cur;
            }else{
                bTail.next = cur;
                bTail = bTail.next;
            }
        }
        //注意点2:不要忘记让cur后移要不然循环会结束不了
        cur = next;
    }
    //注意点3:返回头结点的时候要看看各个部分是否有值
    if(sHead != null){
        sTail.next = eHead;
    }
    if(eHead != null){
        eTail.next = bHead;
    }
    return sHead == null ? (eHead == null ? bHead : eHead) : sHead;
}

这个代码还是有很多需要注意的地方的。

注意点1:这个地方有个next是为了防止cur.next = null的时候把整个链表的后半段丢失。为什么我们要让cur的后一个结点为nill呢?

因为我们要斩断cur与原链表的连接,这样刚好的能让它融入到新的链表。