leetcode 47:全排列II
给定一个可包含重复数字的序列 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
Related Topics
数组
回溯
回溯
因为-10 <= nums[i] <= 10
,所以可以修改原数组的值为flag进行标记,减少空间复杂度。
遍历整个数组,每一个值都可能在这个位置上。(没有被标记的,重复的值选取一个)
- 如果这个值没有被标记过,而且没有在这个位置被选取过(注意第一个值是没有前面的值)
- 保存这个值,然后添加到list,并对这个位置进行标记,继续递归。
- 回溯这个值和list。
class Solution {
List<List<Integer>> lists = new ArrayList<>();
List<Integer> list = new ArrayList<>();
private int flag = -20;
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);
dfs(nums);
return lists;
}
public void dfs(int[] nums){
//找到排列
if(list.size() == nums.length){
lists.add(new ArrayList<>(list));
return;
}
//遍历这个数组 找到合适的数放入进行递归
for(int i = 0 ; i < nums.length;i++){
//1. 这个数不能被选取过
//2. 这个数不能等于前面的值(因为已经排序过 不能选取重复的值)
if(nums[i] != flag &&(i == 0 || nums[i] != nums[i-1])){
//利用原数组将选取的值修改成flag标记
int temp = nums[i];
nums[i] = flag;
list.add(temp);
dfs(nums);
//返回时进行回溯
list.remove(list.size()-1);
nums[i] = temp;
}
}
}
}
解答成功:
执行耗时:1 ms,击败了99.78% 的Java用户
内存消耗:42.3 MB,击败了11.73% 的Java用户