[LeetCode解題攻略] 47. Permutations II

更新 發佈閱讀 6 分鐘

題目描述

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


範例 1

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

範例 2

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

解題思路

此題與 LeetCode 46. Permutations 非常相似,不同的是,輸入的數組可能包含重複的元素,因此我們需要確保返回的排列是唯一的。

解決此問題的關鍵是避免重複。可以採用以下方法:

  1. 排序數組:對輸入數組進行排序,讓相同的數字相鄰排列,便於去重。
  2. 跳過重複元素:在遞迴過程中,如果當前元素與前一個元素相同,且前一個元素尚未使用,則跳過。

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

思路

使用回溯法生成排列,並在選擇元素時進行去重處理:

  1. 將數組排序,讓重複的數字相鄰。
  2. 使用一個布林數組 used 來標記哪些元素已經被使用。
  3. 如果當前數字與前一個數字相同,且前一個數字尚未被使用,則跳過當前數字,避免生成重複的排列。

程式碼

class Solution:
def permuteUnique(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 used[i]:
continue
# 跳過重複的元素
if i > 0 and nums[i] == nums[i - 1] and not used[i - 1]:
continue

# 選擇當前元素
used[i] = True
path.append(nums[i])
backtrack(path, used, res)
# 回溯:撤銷選擇
path.pop()
used[i] = False

nums.sort() # 排序以便去重
res = []
used = [False] * len(nums)
backtrack([], used, res)
return res

時間與空間複雜度

  • 時間複雜度:O(n×n!)
    • 排列的總數最多為 n!,生成每個排列需要 O(n) 的時間。
    • 去重的檢查操作並未改變時間複雜度。
  • 空間複雜度:O(n)
    • 使用了遞迴和布林數組 used

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

思路

  1. 使用交換法來構造排列。
  2. 在每次交換之前,檢查是否出現重複元素,避免生成重複的排列。
  3. 通過集合來記錄當前層的已選擇元素,避免重複交換。

程式碼

class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
def backtrack(start, res):
if start == len(nums):
res.append(nums[:]) # 儲存當前排列
return

seen = set() # 用來記錄本層中已使用的數字
for i in range(start, len(nums)):
# 如果當前數字已被使用,則跳過
if nums[i] in seen:
continue
seen.add(nums[i])
# 交換當前數字到起始位置
nums[start], nums[i] = nums[i], nums[start]
backtrack(start + 1, res)
# 回溯:交換回來
nums[start], nums[i] = nums[i], nums[start]

nums.sort() # 排序以便去重
res = []
backtrack(0, res)
return res

時間與空間複雜度

  • 時間複雜度:O(n×n!)
    • 排列的總數最多為 n!,生成每個排列需要 O(n) 的時間。
  • 空間複雜度:O(n)
    • 使用了遞迴和集合 seen

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

思路

  1. 使用 Python 的內建函數 itertools.permutations 生成所有排列。
  2. 利用集合自動去重。

程式碼

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

時間與空間複雜度

  • 時間複雜度:O(n×n!)
    • 生成所有排列並去重的時間開銷為 O(n×n!)。
  • 空間複雜度:O(n!)
    • 儲存所有唯一排列的集合。

結論

  1. 回溯演算法 是最直觀的方法,適合手動實現和學習。
  2. 遞迴與交換法 是對性能稍作優化的版本。
  3. 如果追求快速實現,使用 內建函數 是不錯的選擇。

希望這篇教學能幫助大家輕鬆理解這道題目!


留言
avatar-img
追極光的北極熊|軟體工程師的小天地
16會員
170內容數
歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
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
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目敘述 Single Number II 給定一個輸入陣列,已知有一個烙單的數字,其他剩餘的數字都恰巧出現三次。 請找出這個烙單的數字。 題目額外提出限制,請使用O(n)線性時間、O(1)常數空間複雜度的演算法。 測試範例 Example 1: Input: nums = [2,2,
Thumbnail
題目敘述 Single Number II 給定一個輸入陣列,已知有一個烙單的數字,其他剩餘的數字都恰巧出現三次。 請找出這個烙單的數字。 題目額外提出限制,請使用O(n)線性時間、O(1)常數空間複雜度的演算法。 測試範例 Example 1: Input: nums = [2,2,
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
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
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,原本裡面包含有整數1到n,但是中間不小心出了差錯,導致有一個數字消失了,而另一個數字重複了。 請找出重複的數字以及消失的數字,並且 以陣列的形式[重複的數字, 消失的數字]返回這兩個數字。 例如: [1,3,3,4] 消失的數字是2,重複的數字是
Thumbnail
題目敘述 題目會給定一個整數陣列nums,原本裡面包含有整數1到n,但是中間不小心出了差錯,導致有一個數字消失了,而另一個數字重複了。 請找出重複的數字以及消失的數字,並且 以陣列的形式[重複的數字, 消失的數字]返回這兩個數字。 例如: [1,3,3,4] 消失的數字是2,重複的數字是
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
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News