📜  回溯以查找所有子集

📅  最后修改于: 2021-05-06 22:29:10             🧑  作者: Mango

给定一组正整数,找到其所有子集。
例子:

Input: array = {1, 2, 3}
Output: // this space denotes null element. 
         1
         1 2
         1 2 3
         1 3
         2
         2 3
         3
Explanation: These are all the subsets that 
can be formed using the array.

Input: 1 2
Output: 
         1 
         2
         1 2
Explanation: These are all the subsets that 
can be formed using the array.

这里已经讨论了迭代解决方案:找到所有子集的迭代方法。本文旨在提供一种回溯方法。

方法:这个想法很简单,如果数组中有n个元素,则每个元素都有两个选择。将该元素包含在子集中或不包含它。
使用上述想法形成了对该问题的递归解决方案。

算法:

  1. 创建一个采用以下参数的递归函数:输入数组,当前索引,输出数组或当前子集,如果需要存储所有子集,则需要数组向量,如果仅需要打印子集,则此空间可以忽略。
  2. 如果当前索引等于数组的大小,则打印子集或输出数组,或者将输出数组插入数组的一个或多个向量中,然后返回。
  3. 完全索引有两种选择。
  4. 忽略当前元素,并使用当前子集和下一个索引(即i + 1)调用递归函数。
  5. 将当前元素插入子集中,并使用当前子集和下一个索引(即i + 1)调用递归函数。

执行:

C++
// CPP program to find all subsets by backtracking.
#include 
using namespace std;
  
// In the array A at every step we have two
// choices for each element either  we can
// ignore the element or we can include the
// element in our subset
void subsetsUtil(vector& A, vector >& res,
                 vector& subset, int index)
{
    res.push_back(subset);
    for (int i = index; i < A.size(); i++) {
  
        // include the A[i] in subset.
        subset.push_back(A[i]);
  
        // move onto the next element.
        subsetsUtil(A, res, subset, i + 1);
  
        // exclude the A[i] from subset and triggers
        // backtracking.
        subset.pop_back();
    }
  
    return;
}
  
// below function returns the subsets of vector A.
vector > subsets(vector& A)
{
    vector subset;
    vector > res;
  
    // keeps track of current element in vector A;
    int index = 0;
    subsetsUtil(A, res, subset, index);
  
    return res;
}
  
// Driver Code.
int main()
{
    // find the subsets of below vector.
    vector array = { 1, 2, 3 };
  
    // res will store all subsets.
    // O(2 ^ (number of elements inside array))
    // because at every step we have two choices
    // either include or ignore.
    vector > res = subsets(array);
  
    // Print result
    for (int i = 0; i < res.size(); i++) {
        for (int j = 0; j < res[i].size(); j++)
            cout << res[i][j] << " ";
        cout << endl;
    }
  
    return 0;
}


Python3
# Python3 program to find all subsets
# by backtracking. 
  
# In the array A at every step we have two 
# choices for each element either we can 
# ignore the element or we can include the 
# element in our subset 
def subsetsUtil(A, subset, index):
    print(*subset)
    for i in range(index, len(A)): 
          
        # include the A[i] in subset. 
        subset.append(A[i])
          
        # move onto the next element. 
        subsetsUtil(A, subset, i + 1) 
          
        # exclude the A[i] from subset and 
        # triggers backtracking.
        subset.pop(-1) 
    return
  
# below function returns the subsets of vector A. 
def subsets(A):
    global res
    subset = []
      
    # keeps track of current element in vector A 
    index = 0
    subsetsUtil(A, subset, index) 
      
# Driver Code
  
# find the subsets of below vector. 
array = [1, 2, 3]
  
# res will store all subsets. 
# O(2 ^ (number of elements inside array)) 
# because at every step we have two choices 
# either include or ignore. 
subsets(array) 
  
# This code is contributed by SHUBHAMSINGH8410


输出:

1 
1 2 
1 2 3 
1 3 
2 
2 3 
3 

复杂度分析:

  • 时间复杂度: O(2 ^ n)。
    对于每个索引,我都会产生两个递归情况,因此时间复杂度为O(2 ^ n)。
  • 空间复杂度: O(n)。
    如果不存储输出数组,并且使用static和global变量存储输出字符串,则可以减少空间复杂度。