解法:选择撤销
和没有重复数字的全排列相比,选择的时候要多加一个条件
如果本轮迭代中,相同的数字已经被选择了,那么就不要选,其他情况就还是一样的
如果判断本轮迭代中相同的数字已经被选择
首先看会出现相同数字的情况, 出现相同数字的时候:num[index] == num[index - 1], 除此之外加一个index > 0防止数组越界,
如果是在本轮迭代中,那么num[index-1]的visited标记已经被撤回了,也就是!visited[index - 1]
所以两个条件加起来就能判断在同一个迭代中,相同的数字已经被选择
具体可以看图示:
时间复杂度:f(n) = n* f(n-1),可以推断出,而f(1) = 1; 所以时间复杂度是O(n!)
空间复杂度:额外需要一个储存visited的数组O(n),以及储存结果的数组O(n平方),因此空间复杂度是O(n平方)
import java.util.*; import java.util.stream.*; import java.util.stream.Collectors; public class Solution { ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); boolean []visited; public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) { LinkedList<Integer> list = new LinkedList<Integer>(); visited = new boolean[num.length]; Arrays.sort(num); permuteUnique(num, list); return result; } private void permuteUnique(int[] num, LinkedList<Integer> list) { if (list.size() == num.length) { result.add(new ArrayList<Integer>(list)); return; } for (int index = 0; index < num.length; index++) { if (visited[index] || (index > 0 && (num[index] == num[index - 1]) && !visited[index - 1])) { continue; } list.add(num[index]); visited[index] = true; permuteUnique(num, list); list.removeLast(); visited[index] = false; } } }