1. 程式人生 > >LeetCode 86 | 連結串列基礎,一次遍歷處理連結串列中所有符合條件的元素

LeetCode 86 | 連結串列基礎,一次遍歷處理連結串列中所有符合條件的元素

本文始發於個人公眾號:**TechFlow**,原創不易,求個關注

今天是LeetCode專題第53篇文章,我們一起來看LeetCode第86題,Partition List(連結串列歸併)。

本題的官方難度是Medium,點贊1276,反對296,通過率大約41%。總體來說,這題質量一般,通過率有點高,整體難度偏簡單,算是一道連結串列的基礎題。對連結串列熟悉一些的同學來說,問題不大。

題意

我們首先來看下題意,題意是說給定一個連結串列以及一個整數x,要求根據x來對連結串列中的元素進行歸併,使得連結串列的前半部分的結果小於x,後半部分的結果大於等於x。其他元素之間的相對順序保持不變。

我們來看樣例:

Input: head = 1->4->3->2->5->2, x = 3
Output: 1->2->2->4->3->5

根據3,我們可以將連結串列當中的元素分成小於3的與大於3的,其中小於3的元素有122,大於等於3的元素有435。我們返回的結果是122和435組成的新連結串列,並且122和435當中元素的互相順序沒有發生變化。

題解

由於問題當中並沒有對我們如何處理連結串列以及當中的元素做出限制,所以我們可以隨意操作這個連結串列以及其中的資料,很容易想到最簡單的方法就是我們根據x將連結串列當中的元素分成兩個部分,分別存入兩個連結串列當中,最後再將這兩個連結串列合併在一起。合併的方式也非常簡單,只需要將連結串列連線在一起即可。

這種思路非常無腦,幾乎不涉及什麼難點,只需要遍歷連結串列然後分別插入不同的連結串列即可,最後再把這兩個連結串列合併成一個就搞定了。

我們很容易就可以寫出程式碼:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        # 建立兩個連結串列
        left = ListNode(0)
        right = ListNode(0)
        # 以及用來遍歷這兩個連結串列的指標
        ln = left
        rn = right
        pnt = head
        while pnt is not None:
            # 小於x則插入left,否則插入right
            if pnt.val < x:
                ln.next = ListNode(pnt.val)
                ln = ln.next
            else:
                rn.next = ListNode(pnt.val)
                rn = rn.next
            pnt = pnt.next
        
        # 將left與right合併
        ln.next = right.next
        return left.next

這樣我們固然做了出來,但是我們是在拋棄原連結串列的基礎上做出來的,畢竟開闢了額外的空間。如果我們想要不建立新的連結串列來解決這題應該怎麼辦呢?

其實也是很簡單的,我們可以遍歷連結串列,如果發現了大於等於x的元素就將它挪到連結串列的最後。這樣當我們遍歷結束的時候,就完成了連結串列的操作。這個思路雖然簡單,但是在實現的時候有很多坑點,需要特別小心。

比如我們需要一個值來記錄遍歷的重點,因為我們在遍歷的時候可能會將一些元素挪到連結串列的最後。所以我們就不能以None來作為終點了,否則會導致死迴圈。我們需要以大於等於x的第一個元素作為結束點,當遍歷到了這個位置的時候結束。還有很多其他關於連結串列操作的細節,我們可以來檢視程式碼:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        tail = head
        if head is None:
            return None
        
        # 找到結尾,當找到了大於等於x的元素就放入結尾後面
        while tail.next is not None:
            tail = tail.next
            
        # 記錄遍歷的終點
        end_point = None
        
        pnt = ListNode(0)
        pnt.next = head
        head = pnt

        while pnt.next is not end_point:
            cur = pnt.next
            if cur.val >= x:
                # 插入在末尾
                tail.next = cur
                tail = cur
                # 如果終點是None的話則進行更新
                # end_point只會更新一次
                if end_point is None:
                    end_point = cur
                pnt.next = cur.next
                continue
            pnt = pnt.next
        tail.next = None
        return head.next

總結

在這題當中,我們面臨的問題是操作連結串列,將連結串列當中的一些元素提取出來放在連結串列最後。無論我們是自己建立新的連結串列來滿足條件,還是在原連結串列的基礎上進行修改,演算法的複雜度都是一樣的,只是空間複雜度不同,也因此帶來的編碼複雜度也不同。相對來說,第一種做法更加簡單一些,第二種稍稍複雜,但是也並不難,只要熟悉連結串列的基本操作,應該都是可以做出來的。

關於連結串列相關的問題我們應該已經做了不少了,今天的題目算是很基礎了,相信大家肯定都沒有問題,我也就不再贅述了。

今天的文章到這裡就結束了,如果喜歡本文的話,請來一波素質三連,給我一點支援吧(關注、轉發、點贊)。

本文使用 mdnice 排版

![](https://user-gold-cdn.xitu.io/2020/7/23/17379cf188c7eeeb?w=258&h=258&f=png&