dfs 排列組合——找全部子集(重複元素和不重複元素)

 

17. 子集

中文
English

給定一個含不一樣整數的集合,返回其全部的子集。python

樣例

樣例 1:markdown

輸入:[0]
輸出:
[
  [],
  [0]
]

樣例 2:app

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

挑戰

你能夠同時用遞歸與非遞歸的方式解決麼?spa

注意事項

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

 

時間複雜度是O(2^n),本質就是在作二叉樹的dfs。[1,2,3]舉例:blog

              root遞歸

             /   \ip

         不選中1  選中1get

       /    \           /      \it

不選中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()

 

 

含有重複元素的子集問題,例如【1,2,2,3】

                                                root (path=[])

                                                                       |

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

                                    |                                   |                  |                |

                                    1                                   2                2(重複)       3

                                  /   \                               /  \              |

                                2      3                           2     3            3

                               / \                                  |

                             2    3                                3

                             |

                            3

又例如【1,1,2,3】

                                                root (path=[])

                                                                       |

                                    ----------------|-------------------------

                                    |                           1(重複)         |                           |

                                    1                         / \                   2                          3

                                  / |  \                    2    3                 |

                                1    2   3                 |                       3

                               / \   |                      3        

                             2   3  3                              

                             |

                            3

因此代碼以下:

class Solution:
    """
    @param nums: A set of numbers.
    @return: A list of lists. All valid subsets.
    """
    def subsetsWithDup(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))
        
        for i in range(index, len(nums)):
            if i > 0 and nums[i] == nums[i-1] and i > index:
                continue
            
            path.append(nums[i])
            self.dfs(nums, i+1, path, result)
            path.pop()
相關文章
相關標籤/搜索