这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战
题目
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例
输入: nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
输入: 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
解题思路
回溯
对于全排列的题来说,大多数的解法都是采用回溯算法来实现的。我们需要从左到右依次将数组中的元素与其余元素进行组合,这种类似穷举的操作,可以采用【回溯】来模拟该过程。
同时题目要求是返回所有不重复的排列,那么我们还需要在原有的基础上做一个剪枝操作,将重复的元素剔除掉,以保证结果的唯一性。
class Solution {
private List<List<Integer>> list;
private boolean[] vis;
public List<List<Integer>> permuteUnique(int[] nums) {
int len = nums.length;
list = new ArrayList<>();
if(0 == len){
return list;
}
vis = new boolean[len];
// 这里需要先进行一个排序操作,便于后面进行剪枝判断
Arrays.sort(nums);
dfs(nums, 0, len, new LinkedList<Integer>());
return list;
}
public void dfs(int[] nums, int index, int n, LinkedList<Integer> numList){
// 添加新的排列并结束
if(index == n){
list.add(new ArrayList(numList));
return;
}
for(int i = 0; i < n; ++i){
// 剪枝判断,vis[i]为true表示已经遍历过该元素,则跳过当前循环
// 或者当前元素与前面元素一致,表示以遍历过该组合,也跳过循环
if(vis[i] || (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1])){
continue;
}
vis[i] = true;
// 添加元素
numList.add(nums[i]);
// 向下延伸
dfs(nums, index + 1, n, numList);
// 回溯
numList.removeLast();
vis[i] = false;
}
}
}
复杂度分析
- 时间复杂度:
- 空间复杂度:
最后
文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!
如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!