dfs 排列组合——找所有子集

17. 子集

中文
English

给定一个含不同整数的集合,返回其所有的子集。

样例

样例 1:

输入:[0]
输出:
[
  [],
  [0]
]

样例 2:

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

挑战

你可以同时用递归与非递归的方式解决么?

注意事项

子集中的元素排列必须是非降序的,解集必须不包含重复的子集。

时间复杂度是O(2^n),本质就是在做二叉树的dfs。[1,2,3]举例:

              root

             /   \

         不选中1  选中1

       /    \           /      \

不选中2  选中2  不选中2  选中2

 。。。。。

使用dfs记录遍历路径即可。

class Solution:
    """
    @param nums: A set of numbers
    @return: A list of lists
    """
    def subsets(self, nums):
        # write your code here
        path, results = [],[]
        self.helper(sorted(nums), 0, path, results)
        return results
    
    
    def helper(self, nums, index, path, results):
        if index == len(nums):
            results.append(list(path))
            return
        
        path.append(nums[index])
        self.helper(nums, index+1, path, results)
        
        path.pop()
        self.helper(nums, index+1, path, results)

第二种写法是使用位运算,也比较直观,代码很容易写出来:

class Solution:
    """
    @param nums: A set of numbers
    @return: A list of lists
    """
    def subsets(self, nums):
        # write your code here
        nums = sorted(nums)
        n = len(nums)
        results = []
        for i in range(1<<n):
            results.append(self.get_num(nums, i, n))
        return results
    
    
    def get_num(self, nums, num, cnt):
        result = []
        for i in range(cnt):
            if num & (1<<i):
                result.append(nums[i])
        return result

第三种写法是使用for dfs写法,看下面的图,以【1,2,3】为例:

                                                                    root (path=[])

                                                                       |

                                    ----------------------------------------

                                    |                                   |                                  |

                                    1                                   2                                 3

                                  /   \                                 |

                                2      3                               3

                               /

                             3

在遍历上述树的过程中将path全部记录下来(path不用走到叶子节点):

class Solution:
    """
    @param nums: A set of numbers
    @return: A list of lists
    """
    def subsets(self, nums):
        # write your code here
        nums = sorted(nums)
        path, result = [], []
        self.dfs(nums, 0, path, result)
        return result
    
    
    def dfs(self, nums, index, path, result):
        result.append(list(path))
        
        if index == len(nums):
            return
        
        for i in range(index, len(nums)):
            path.append(nums[i])
            self.dfs(nums, i+1, path, result)
            path.pop()

猜你喜欢

转载自www.cnblogs.com/bonelee/p/11667428.html