LeetCode-47. 全排列 II
阿新 • • 發佈:2022-04-07
題目來源
題目詳情
給定一個可包含重複數字的序列 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]]
提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
相似題目
LeetCode-78. 子集
LeetCode-46. 全排列
LeetCode-47. 全排列 II
題解詳情
解法一:回溯
本題與[LeetCode-46. 全排列]和[LeetCode-78. 子集]這兩道題目都十分相似,主要是遞迴和回溯演算法的考察。
與全排列題目相比,這道題目增加的一個難度就是將無重複元素改成了有重複元素,這就使得我們無法使用全排列這道題目的解題思路來解決問題了。但是,我們需要知道的,我們都需要使用回溯來列舉到所有滿足條件的排列,關鍵是如何篩選掉可能重複的排列。
這裡,我們可以首先將陣列進行排序,這樣就可以使得相同的元素是相鄰的,也就減少了我們處理的複雜度。更具體地,我們可以在列舉下標的時候判斷前一個元素是否是相同的,如果前一個元素沒有遍歷過而且是與當前元素相同,那麼可以跳過當前元素,因為當前元素一定會被前一個元素列舉在內,這樣就達到了去重的目的。
class Solution { boolean[] vis;// 記錄已經遍歷過的位置下標 List<List<Integer>> result; public List<List<Integer>> permuteUnique(int[] nums) { vis = new boolean[nums.length]; result = new LinkedList<>(); Arrays.sort(nums); dfs(nums, 0, new LinkedList<Integer>()); return result; } private void dfs(int[] nums, int num, LinkedList<Integer> list){ int n = nums.length; if(num == n){ result.add(new LinkedList<Integer>(list)); return; } for(int i=0; i<n; i++){ if(vis[i] || (i > 0 && !vis[i-1] && nums[i] == nums[i-1])){ continue; } vis[i] = true; list.add(nums[i]); dfs(nums, num+1, list); list.removeLast(); vis[i] = false; } } }