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

 

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