本文始發於個人公眾號: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 排版