回溯查找所有子集
给定一组正整数,求其所有子集。 例:
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。
- 在子集中插入当前元素,用当前子集和下一个索引调用递归函数,即+ 1。
执行:
Java 语言(一种计算机语言,尤用于创建网站)
/*package whatever //do not write package name here */
import java.io.*;
import java.util.*;
class GFG {
public static void
findSubsets(List<List<Integer>> subset, ArrayList<Integer> nums, ArrayList<Integer> output, int index)
{
// Base Condition
if (index == nums.size()) {
subset.add(output);
return;
}
// Not Including Value which is at Index
findSubsets(subset, nums, new ArrayList<>(output), index + 1);
// Including Value which is at Index
output.add(nums.get(index));
findSubsets(subset, nums, new ArrayList<>(output), index + 1);
}
public static void main(String[] args) {
//Main List for storing all subsets
List<List<Integer>> subset = new ArrayList<>();
// Input ArrayList
ArrayList<Integer> input = new ArrayList<>();
input.add(1);
input.add(2);
input.add(3);
findSubsets(subset, input, new ArrayList<>(), 0);
// Comparator is used so that all subset get
// sorted in ascending order of values
Collections.sort(subset, (o1, o2) -> {
int n = Math.min(o1.size(), o2.size());
for (int i = 0; i < n; i++) {
if (o1.get(i) == o2.get(i)){
continue;
}else{
return o1.get(i) - o2.get(i);
}
}
return 1;
});
// Printing Subset
for(int i = 0; i < subset.size(); i++){
for(int j = 0; j < subset.get(i).size(); j++){
System.out.print(subset.get(i).get(j) + " ");
}
System.out.println();
}
}
}
Python 3
# 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
C++
// CPP program to find all subsets by backtracking.
#include <bits/stdc++.h>
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<int>& A, vector<vector<int> >& res,
vector<int>& 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<vector<int> > subsets(vector<int>& A)
{
vector<int> subset;
vector<vector<int> > 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<int> 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<vector<int> > 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;
}
Output
1
1 2
1 2 3
1 3
2
2 3
3
复杂度分析:
- 时间复杂度: O(n(2 ^ n))。 对于每个索引 I,都会产生两个递归情况,因此时间复杂度为 O(2^n).如果我们包括将子集向量复制到 res 向量所花费的时间,所花费的时间将等于子集向量的大小。
- 空间复杂度: O(n)。 如果不存储输出数组,使用静态全局变量存储输出字符串,可以降低空间复杂度。
版权属于:月萌API www.moonapi.com,转载请注明出处