[LeetCode解題攻略] 46. Permutations

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

題目描述

給定一個不含重複數字的整數陣列 nums,返回所有可能的排列。


範例 1

輸入: nums = [1, 2, 3]
輸出: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

範例 2

輸入: nums = [0, 1]
輸出: [[0,1],[1,0]]

範例 3

輸入: nums = [1]
輸出: [[1]]

解題思路

這是一道經典的排列組合問題。對於給定的數組,我們需要找到所有元素的排列組合。有幾種方法可以實作。


解法一:回溯演算法 (Backtracking)

思路

回溯法是解決排列組合問題的常用方法。主要步驟如下:

  1. 使用一個遞迴函數來構造每種排列。
  2. 使用一個布林數組來標記哪些元素已經被選中。
  3. 當排列長度等於 nums 長度時,將當前排列加入結果。
  4. 回溯時取消當前選擇,繼續探索其他可能性。

程式碼

class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
def backtrack(path, used, res):
# 當排列長度等於輸入長度,將排列加入結果
if len(path) == len(nums):
res.append(path[:]) # 複製當前排列
return

for i in range(len(nums)):
if not used[i]: # 如果該數字未被使用
# 選擇當前數字
used[i] = True
path.append(nums[i])
# 繼續遞迴
backtrack(path, used, res)
# 回溯:撤銷選擇
path.pop()
used[i] = False

res = []
used = [False] * len(nums) # 用來標記元素是否被使用
backtrack([], used, res)
return res

時間與空間複雜度

  • 時間複雜度:O(n×n!)
    • 每個排列長度為 n,有 n! 種排列組合。
  • 空間複雜度:O(n)
    • 使用了 backtrack 函式以及 used 陣列。

解法二:遞迴與交換法 (Recursive Swapping)

思路

  1. nums 視為一個待排列的陣列。
  2. 透過交換元素來構造每種排列。
  3. 每次將當前位置的數字與其後任意位置的數字交換,遞迴處理後續排列。
  4. 回溯時將數字交換回來。

程式碼

class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
def backtrack(start, res):
# 當起始位置等於陣列長度時,將排列加入結果
if start == len(nums):
res.append(nums[:]) # 複製當前排列
return

for i in range(start, len(nums)):
# 交換當前數字到起始位置
nums[start], nums[i] = nums[i], nums[start]
# 繼續遞迴
backtrack(start + 1, res)
# 回溯:交換回來
nums[start], nums[i] = nums[i], nums[start]

res = []
backtrack(0, res)
return res

時間與空間複雜度

  • 時間複雜度:O(n×n!)
    • 同樣需要生成所有排列,且每個排列長度為 n。
  • 空間複雜度:O(n)
    • 由遞迴深度決定。

解法三:內建函數 (Python itertools.permutations)

思路

  1. Python 提供了 itertools.permutations,可以直接生成所有排列。
  2. 使用該函數可以大幅簡化程式碼。

程式碼

from itertools import permutations
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
return list(permutations(nums))

時間與空間複雜度

  • 時間複雜度:O(n×n!)
    • itertools.permutations 底層也是基於生成所有排列。
  • 空間複雜度:O(n!)
    • 儲存所有排列。

結論

  1. 回溯演算法 是最常用的手動實現方法,適合理解排列生成的過程。
  2. 遞迴與交換法 適合追求更少空間開銷的情況。
  3. 如果時間緊迫,可以直接使用 內建函數

希望這篇解題教學對大家有幫助!


留言
avatar-img
留言分享你的想法!
avatar-img
追極光的北極熊|軟體工程師的小天地
10會員
162內容數
歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
2025/04/04
給定一個非負整數陣列 nums,其中 nums[i] 代表你在索引 i 處最多可以向右跳幾步。 請判斷是否能夠從索引 0 跳到最後一個索引。
2025/04/04
給定一個非負整數陣列 nums,其中 nums[i] 代表你在索引 i 處最多可以向右跳幾步。 請判斷是否能夠從索引 0 跳到最後一個索引。
2025/03/28
給定一個 m x n 的矩陣 matrix,請按照 螺旋順序(spiral order) 返回矩陣中的所有元素。
2025/03/28
給定一個 m x n 的矩陣 matrix,請按照 螺旋順序(spiral order) 返回矩陣中的所有元素。
2025/03/20
這道題是 LeetCode 的經典題之一,要求我們找出 一個子陣列,使其和最大,並返回這個最大和的數值。
2025/03/20
這道題是 LeetCode 的經典題之一,要求我們找出 一個子陣列,使其和最大,並返回這個最大和的數值。
看更多
你可能也想看
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目敘述 Combination Sum IV 給定一個輸入陣列nums,和目標值target,從nums裡面挑數字去湊出總和 = target,數字可以重複挑選。 請問有多少排列數可以湊出target? 註: 排列數的意思就是位置不同代表兩種不同的方法數。
Thumbnail
題目敘述 Combination Sum IV 給定一個輸入陣列nums,和目標值target,從nums裡面挑數字去湊出總和 = target,數字可以重複挑選。 請問有多少排列數可以湊出target? 註: 排列數的意思就是位置不同代表兩種不同的方法數。
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給定我們一個整數陣列nums,要求我們把裡面的0做元素交換,把0都搬到陣列的右邊。題目要求必須in-place在原本的陣列裡面做操作,不可以額外建立新的陣列。 題目的原文敘述 測試範例 Example 1: Input: nums = [0,1,0,3,12] Outpu
Thumbnail
題目敘述 題目會給定我們一個整數陣列nums,要求我們把裡面的0做元素交換,把0都搬到陣列的右邊。題目要求必須in-place在原本的陣列裡面做操作,不可以額外建立新的陣列。 題目的原文敘述 測試範例 Example 1: Input: nums = [0,1,0,3,12] Outpu
Thumbnail
題目敘述 題目會給我們一個參數k 和 目標值n。 請問我們從1~9內挑k個相異的數字,使得他們的總和為n 的組合數有多少? 挑選時,每個數字必須相異,而且每個數字只能選一次。 題目的原文敘述 測試範例 Example 1: Input: k = 3, n = 7 Output: [
Thumbnail
題目敘述 題目會給我們一個參數k 和 目標值n。 請問我們從1~9內挑k個相異的數字,使得他們的總和為n 的組合數有多少? 挑選時,每個數字必須相異,而且每個數字只能選一次。 題目的原文敘述 測試範例 Example 1: Input: k = 3, n = 7 Output: [
Thumbnail
題目敘述 題目給定我們一個輸入陣列nums 要求我們以正、負交叉排列的方式重組陣列,並且必須保持原本的相對順序。 並且以陣列的形式輸出返回答案。 例[5, 1, -2, -3] 重排後為 [5, -2, 1, -3] 題目的原文敘述 測試範例 Example 1: Input:
Thumbnail
題目敘述 題目給定我們一個輸入陣列nums 要求我們以正、負交叉排列的方式重組陣列,並且必須保持原本的相對順序。 並且以陣列的形式輸出返回答案。 例[5, 1, -2, -3] 重排後為 [5, -2, 1, -3] 題目的原文敘述 測試範例 Example 1: Input:
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News