力扣题目
解题思路
java代码
力扣题目:
给定一个可包含重复数字的序列 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]]
解题思路:
算法原理:
使用回溯法来生成全排列。通过递归地选择数字并加入临时列表,当临时列表长度达到原始数组长度时,将其加入结果列表。为了处理重复元素,在选择数字时进行了一些条件判断来跳过重复的情况。
思路:
- 首先对输入数组进行排序,以便后续能够方便地判断重复情况。
- 在回溯函数中,对于每个数字,只有在未被使用且不是重复数字的情况下,才将其加入临时列表,并进行递归调用。
- 递归调用完成后,将该数字从临时列表中移除,并标记为未使用,以便进行其他可能的排列。
代码分析:
permuteUnique
方法是主函数,初始化结果列表,对数组排序,然后调用回溯函数。backtrack
方法是回溯函数。- 如果临时列表长度达到数组长度,将其加入结果列表。
- 遍历数组,对于每个数字,通过条件判断决定是否选择该数字。如果可以选择,将其加入临时列表,标记为已使用,进行递归调用,然后恢复状态(移除数字,标记为未使用)。
时间复杂度:O(n*n!),其中 是数组的长度。
空间复杂度:O(n),主要用于递归栈和存储临时列表和结果列表。
java代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class PermutationsII {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums); // 先排序,方便后续去重
backtrack(result, new ArrayList<>(), nums, new boolean[nums.length]);
return result;
}
public void backtrack(List<List<Integer>> result, List<Integer> tempList, int[] nums, boolean[] used) {
if (tempList.size() == nums.length) {
result.add(new ArrayList<>(tempList));
return;
}
for (int i = 0; i < nums.length; i++) {
// 如果当前数字已经使用过,或者和前一个相同且前一个未使用,跳过
if (used[i] || (i > 0 && nums[i] == nums[i - 1] &&!used[i - 1])) {
continue;
}
used[i] = true;
tempList.add(nums[i]);
backtrack(result, tempList, nums, used);
used[i] = false;
tempList.remove(tempList.size() - 1);
}
}
public static void main(String[] args) {
int[] nums = {1, 1, 2};
PermutationsII permutationsII = new PermutationsII();
List<List<Integer>> permutations = permutationsII.permuteUnique(nums);
for (List<Integer> permutation : permutations) {
System.out.println(permutation);
}
}
}
更多详细内容同步到公众号,感谢大家的支持!
每天都会给刷算法的小伙伴推送明日一题,并且没有任何收费项