LSGO——LeetCode实战(数组系列):78题 子集(Subsets)

 

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3]
输出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

解法一:位运算

这个方法最核心的思想是第i个子集的二进制正好对应着其子集。对应关系如下:

如输入 [1,2,3],输出排列方式有8种,依次将1往左移位和原数进行与运算 1&lt;&lt;j&amp;i 1&lt;&lt;j \quad \&amp;\quad i1<<j&i

[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

可以对应到如下的8中标记

0 0 0 , 0 0 1 , 0 1 0 , 0 1 1,1 0 0 , 1 0 1 , 1 1 0 , 1 1 1
其中很明显可以看出一个子集中存在的元素正好对应着位为1。

第一步:我们计算有2**len(nums)个子集。

第二步:i个子集对应着数i。利用位运算,如果1 << j & i 得到的结果不为0,则说明本子集第j个元素存在。

简化版代码:运行时间相比于下面那个代码更长

class Solution(object):
    def subsets(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        ans = []
        for i in range(2**len(nums)):
            ans.append([nums[j] for j in range(len(nums)) if 1 << j & i])
        return ans

 

下面这个代码更容易理解一些:

class Solution(object):
    def subsets(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        len_nums = len(nums)
        total = 2**len_nums
        res =[]
        for i in range(total):
            flag_list = [0 for k in range(len_nums)]  # 用flag_list标记对应的每个是否存在
            for j in range(len_nums):
                bit = 1<<j
                if bit & i:
                    flag_list[j] = 1
            lists = [nums[j]  for j in range(len_nums) if flag_list[j] == 1]
            res.append(lists)
        return res

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章