Subsets II
Given a collection of integers that might contain duplicates, nums, return all possible subsets.
Note:
- Elements in a subset must be in non-descending order.
- The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,2]
, a solution is:
[ [2], [1], [1,2,2], [2,2], [1,2], [] ]
分析:
生成子集,这里的给定的子集元素有重复,要求生成的子集无重复。我在之前的博客中写过一篇生成子集的文章,这里先使用位向量法。
代码:
from itertools import compress
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
solutions = []
self.dfs(0, len(nums), [], nums, solutions)
return sorted(solutions)
def dfs(self, cur, n, lst, nums, solutions):
if cur == n:
cur_ans = sorted(list(compress(nums, lst)))
if cur_ans not in solutions:
solutions.append(cur_ans)
else:
self.dfs(cur + 1, n, lst + [0], nums, solutions)
self.dfs(cur + 1, n, lst + [1], nums, solutions)
在有重复元素的情况下,使用这种方法的代码效率并不高。
上述代码是选择决定第i个位置的元素是否选或者不选的,当给定nums为[1, 1, 2]时,选择了第一个元素和最后一个元素结果与选择了第二个元素和最后一个元素的结果想同,这样会产生重复的情况。
下面的代码能够在递归时生成的解均为非重复解。
代码:
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
nums.sort()
self.dfs(nums, len(nums), 0, [], res)
return res
def dfs(self, nums, n, cur, path, res):
res.append(path)
for i in range(cur, n):
if i > cur and nums[i] == nums[i - 1]: # 剔除重复的情况。
# print i, cur, nums[i]
continue
self.dfs(nums, n, i + 1, path + [nums[i]], res)
上面的代码,在递归时不产生重复的解。比如当nums为[1, 1, 1, 3]时,递归会先产生[]一直到[1, 1, 1, 3],然后递归开始回退,回退到res为[1, 1]状态然后产生[1, 1, 3],然后递归继续回退,回退到res为[1](此时res中的元素1为nums中的第一个元素1)的状态然后准备添加nums中第三个元素1,而此时发现第三个元素与第二个元素值相同,则放弃添加该元素,转而添加nums中的第四个元素3,得到[1, 3],...
当递归回退后,程序不再添加相邻相同元素,这样就避免了产生相同的解,提高了效率。