[LeetCode解題攻略] 24. Swap Nodes in Pairs

更新於 發佈於 閱讀時間約 6 分鐘

題目描述

給定一個鏈表,每次交換相鄰的兩個節點,返回交換後的鏈表。要求在不改變節點值的情況下進行節點交換(即直接操作鏈表結構)。

條件

  • 鏈表的長度範圍是 0 <= n <= 100
  • 節點的值範圍是 0 <= Node.val <= 100

範例 1:

Input: head = [1,2,3,4]
Output: [2,1,4,3]
raw-image

範例 2:

Input: head = []
Output: []

範例 3:

Input: head = [1]
Output: [1]

範例 4:

Input: head = [1,2,3]
Output: [2,1,3]

解題思路

解題的核心是理解如何操作鏈表結構來交換節點,而不是僅僅交換節點的值。可以使用以下幾種方法解決該問題:

  1. 遞迴法:以遞迴的方式處理交換,逐步處理剩餘鏈表。
  2. 迭代法:利用指針操作,逐段交換相鄰的節點。

解法一:遞迴法

思路

  1. 如果鏈表為空或只有一個節點,直接返回該鏈表。
  2. 交換當前的兩個節點後,將後續鏈表遞迴處理。
  3. 將處理後的結果鏈接到已交換的節點。

程式碼

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 基本情況:鏈表為空或只有一個節點
if not head or not head.next:
return head

# 交換第一對節點
new_head = head.next
head.next = self.swapPairs(new_head.next)
new_head.next = head

return new_head

時間與空間複雜度

  • 時間複雜度
    每次遞迴處理兩個節點,總共有 n/2 次操作,因此時間複雜度為 O(n),其中 n 是鏈表的節點數。
  • 空間複雜度
    由於使用遞迴,每次遞迴都需要額外的函數調用棧,最深遞迴深度為 n/2,空間複雜度為 O(n)。

解法二:迭代法

思路

  1. 使用虛擬節點(dummy node)作為輔助,方便處理頭節點的交換。
  2. 每次交換相鄰的兩個節點,並更新指針以處理下一對節點。
  3. 最後返回新的頭節點。

程式碼

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 創建一個虛擬節點
dummy = ListNode(0)
dummy.next = head
prev = dummy

# 遍歷鏈表,逐對交換節點
while prev.next and prev.next.next:
first = prev.next
second = first.next

# 交換節點
prev.next = second
first.next = second.next
second.next = first

# 移動 prev 指針到下一對節點前
prev = first

return dummy.next

時間與空間複雜度

  • 時間複雜度
    每次迭代處理兩個節點,總共有 n/2 次操作,因此時間複雜度為 O(n)。
  • 空間複雜度
    迭代過程中使用常數額外空間,空間複雜度為 O(1)。

總結

  1. 遞迴法 適合小型鏈表,程式碼簡潔但可能受到遞迴深度限制。
  2. 迭代法 是處理長鏈表的最佳選擇,時間與空間效率更高。

選擇適合的解法取決於具體場景,迭代法通常是更通用的解法。

歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
給定 k 個遞增排序的鏈表,將它們合併成一個遞增排序的鏈表,並返回合併後的鏈表。
給定一個整數 n,請生成所有可能由 n 對括號組成的 有效括號組合。
給定兩個遞增排序的鏈表 list1 和 list2,將它們合併為一個新的 遞增排序 的鏈表,並返回這個新鏈表。新的鏈表應該由這兩個鏈表中的節點組成,而不應創建新的節點。最後回傳合併後的鍊錶的頭節點。
給定一個僅包含字元 '(', ')', '{', '}', '[' 和 ']' 的字串 s,確定輸入字串是否有效。
給定一個Linked list的head,從這個Linked list的末尾刪除第 n 個節點並返回其head。
給定一個包含 n 個整數的陣列 nums,傳回所有唯一的四元組 [nums[a], nums[b], nums[c], nums[d]] 的數組,使得該答案滿足題目的每項要求。
給定 k 個遞增排序的鏈表,將它們合併成一個遞增排序的鏈表,並返回合併後的鏈表。
給定一個整數 n,請生成所有可能由 n 對括號組成的 有效括號組合。
給定兩個遞增排序的鏈表 list1 和 list2,將它們合併為一個新的 遞增排序 的鏈表,並返回這個新鏈表。新的鏈表應該由這兩個鏈表中的節點組成,而不應創建新的節點。最後回傳合併後的鍊錶的頭節點。
給定一個僅包含字元 '(', ')', '{', '}', '[' 和 ']' 的字串 s,確定輸入字串是否有效。
給定一個Linked list的head,從這個Linked list的末尾刪除第 n 個節點並返回其head。
給定一個包含 n 個整數的陣列 nums,傳回所有唯一的四元組 [nums[a], nums[b], nums[c], nums[d]] 的數組,使得該答案滿足題目的每項要求。
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
給定一個輸入陣列,每一個tuple代表節點之間了從屬關係。 請從從屬關係重建整顆二元樹,並且返回整顆二元樹的根結點。
Thumbnail
題目敘述 Merge Nodes in Between Zeros 給定一個鏈結串列,合併非零區間的節點(以加總的方式合併),輸出合併後的鏈結串列。
Thumbnail
題目敘述 題目給定一個鏈結串列中的節點Node,要求我們從鏈結串列中刪除該節點。 題目保證該節點不是tail node。 題目要求我們in-place原位操作。 原本的英文題目敘述 測試範例 Example 1: Input: head = [4,5,1,9], node = 5
Thumbnail
題目敘述 輸入給定一個鏈結串列的head node。 要求我們進行化簡,只要某個節點的右手邊存在比較大的節點,就刪除掉。 例如 5->2->13->3 5的右手邊有13,所以5刪除掉。 2的右手邊有13,所以2刪除掉。 13的右手邊沒有更大的節點,所以13留著。 3的右手邊沒有更大
Thumbnail
題目敘述 題目會給定一個鏈結串列的起始點,要求我們把其中區間總和為0的部分刪除掉。 例如 1→ 2 → -2 → 3 → 4 裡面有一段是2 → -2 區間總和為零,所以簡化刪除後變成 1→ 3 → 4 題目的原文敘述 測試範例 Example 1: Input: head
Thumbnail
題目敘述 題目會給定一個鏈結串列 Linked List的頭部結點,要求我們根據索引的奇偶數重新排列。奇數索引的在前,偶數索引的在後。數的時候,從Head節點的索引=1開始數。 例如: 1 -> 2 -> 3 -> 4 -> 5 重新排列為 1 -> 3 -> 5 -> 2 -> 4
Thumbnail
題目敘述 題目會給定我們一條鏈結串列Linked list的起始節點,要求我們刪除Linked List正中央的節點。 註: 正中央的節點,題目定義為索引為floor( 串列長度 / 2 ) 的節點,索引從零(Head Node)出發開始數。 例如 1 -> 2 -> 3 -> 4 鏈結
Thumbnail
題目敘述 題目會給定我們兩個輸入字串word1, word2,要求我們依照word1,word2,word1,word2, ... 交叉前進的方式,合併兩個字串,作為輸出。 題目的原文敘述 測試範例 Example 1: Input: word1 = "abc", word2 = "pq
Thumbnail
題目會給定我們一個輸入陣列connections,和城市的總數目n。 輸入陣列裡面是以pair的方式儲存,(a, b) 分邊代表這條邊的起點和終點。 請問,我們需要改變多少條邊的方向,才能讓每條路徑都指向編號零號的城市( City #0)? 註: 題目還保證,在改變方向之後,一定可以讓每座城
Thumbnail
題目敘述 題目會給定我們兩個字串word1 和 word2。 允許我們不限制次數進行下列兩種操作: 任意調換其中兩個字元的位置。 把字串中的某個字元全部置換成另一個字元,同時把另一個字元同時置換成某個字元。(例如把字串中原本的a都換成b,把原本的b都換成a) 問我們能不能通過上述兩項操作,
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
給定一個輸入陣列,每一個tuple代表節點之間了從屬關係。 請從從屬關係重建整顆二元樹,並且返回整顆二元樹的根結點。
Thumbnail
題目敘述 Merge Nodes in Between Zeros 給定一個鏈結串列,合併非零區間的節點(以加總的方式合併),輸出合併後的鏈結串列。
Thumbnail
題目敘述 題目給定一個鏈結串列中的節點Node,要求我們從鏈結串列中刪除該節點。 題目保證該節點不是tail node。 題目要求我們in-place原位操作。 原本的英文題目敘述 測試範例 Example 1: Input: head = [4,5,1,9], node = 5
Thumbnail
題目敘述 輸入給定一個鏈結串列的head node。 要求我們進行化簡,只要某個節點的右手邊存在比較大的節點,就刪除掉。 例如 5->2->13->3 5的右手邊有13,所以5刪除掉。 2的右手邊有13,所以2刪除掉。 13的右手邊沒有更大的節點,所以13留著。 3的右手邊沒有更大
Thumbnail
題目敘述 題目會給定一個鏈結串列的起始點,要求我們把其中區間總和為0的部分刪除掉。 例如 1→ 2 → -2 → 3 → 4 裡面有一段是2 → -2 區間總和為零,所以簡化刪除後變成 1→ 3 → 4 題目的原文敘述 測試範例 Example 1: Input: head
Thumbnail
題目敘述 題目會給定一個鏈結串列 Linked List的頭部結點,要求我們根據索引的奇偶數重新排列。奇數索引的在前,偶數索引的在後。數的時候,從Head節點的索引=1開始數。 例如: 1 -> 2 -> 3 -> 4 -> 5 重新排列為 1 -> 3 -> 5 -> 2 -> 4
Thumbnail
題目敘述 題目會給定我們一條鏈結串列Linked list的起始節點,要求我們刪除Linked List正中央的節點。 註: 正中央的節點,題目定義為索引為floor( 串列長度 / 2 ) 的節點,索引從零(Head Node)出發開始數。 例如 1 -> 2 -> 3 -> 4 鏈結
Thumbnail
題目敘述 題目會給定我們兩個輸入字串word1, word2,要求我們依照word1,word2,word1,word2, ... 交叉前進的方式,合併兩個字串,作為輸出。 題目的原文敘述 測試範例 Example 1: Input: word1 = "abc", word2 = "pq
Thumbnail
題目會給定我們一個輸入陣列connections,和城市的總數目n。 輸入陣列裡面是以pair的方式儲存,(a, b) 分邊代表這條邊的起點和終點。 請問,我們需要改變多少條邊的方向,才能讓每條路徑都指向編號零號的城市( City #0)? 註: 題目還保證,在改變方向之後,一定可以讓每座城
Thumbnail
題目敘述 題目會給定我們兩個字串word1 和 word2。 允許我們不限制次數進行下列兩種操作: 任意調換其中兩個字元的位置。 把字串中的某個字元全部置換成另一個字元,同時把另一個字元同時置換成某個字元。(例如把字串中原本的a都換成b,把原本的b都換成a) 問我們能不能通過上述兩項操作,