全排列II
1.解法
这道题和简单全排列的区别在于,集合中有重复元素,所以我们只要使用一种方法去重即可。
如果不明白简单全排列要怎么做的,可以看我以前的博客(全排列)
先画出树图:
首先我们先讲为什么需要去重,换句话说,为什么会产生重复解?
举个例子,比如[1,1,2]。
对于第一个1而言,如果先把他选出来,那么对于剩余集合[1,2]而言,就可以产生[1,1,2]、[1,2,1]两个解。
然后我们来看第二个1,如果先把他选出来,那么剩余集合也是[1,2],这样也会产生两个解,[1,1,2]、[1,2,1],和上面就重复了
因此我们需要有一个集合来记录这个集合中哪些元素已经被选择过了,这样在后面做选择时,如果第一个选的元素已经在这个集合里面了,就直接跳过。
举个例子,还是[1,1,2]。做记录的集合我们记为used1
首先选择第一个1,然后产生两个解[1,1,2]、[1,2,1],并且1进入used1。
然后选择第二个1,发现1已经在used1中了,直接跳过。这样就避免了重复解。
所以我们在之前简单全排列的基础上加上used1来记录即可。
def permuteUnique(nums):
result = []
path = []
used = [0] * len(nums)
def backtracking(nums,used):
used1 = set() # 注意used1要声明在递归函数里面,因为(树中)每下一层used1就要重新记录
if len(nums)==len(path):
path1 = path.copy()
result.append(path1)
return
for i in range(len(nums)):
if used[i]==1:
continue
if nums[i] in used1:
continue
path.append(nums[i])
used1.add(nums[i]) # 添加即可
used[i] = 1
backtracking(nums,used)
used[i] = 0
path.pop()
backtracking(nums,used)
return result
2.总结
去重的方法:
- 组合问题:集合中含重复元素:
nums = sorted(nums)
if i > startindex and nums[i] == nums[i-1]:
continue
- 组合问题:集合中含重复元素,并且集合不允许排序
used = set()
for i in range():
used.add(nums[i])
- 排列问题:集合中含重复元素(和第二种情况一致)
used = set()
for i in range():
used.add(nums[i])