📌  相关文章
📜  使用BitMasking方法查找给定集合的所有不同子集

📅  最后修改于: 2021-05-06 18:05:38             🧑  作者: Mango

给定一组正整数,找到其所有子集。该集合可以包含重复的元素,因此任何重复的子集在输出中仅应考虑一次。
例子:

Input:  S = {1, 2, 2}
Output:  {}, {1}, {2}, {1, 2}, {2, 2}, {1, 2, 2}

Explanation: 
The total subsets of given set are - 
{}, {1}, {2}, {2}, {1, 2}, {1, 2}, {2, 2}, {1, 2, 2}
Here {2} and {1, 2} are repeated twice so they are considered 
only once in the output

先决条件:电源设置
这个想法是使用位掩码模式来生成所有组合,如先前的文章中所述。但是,如果元素在给定的集合中重复,则先前的文章将打印重复的子集。为了处理重复的元素,我们从给定的子集构造一个字符串,这样具有相似元素的子集将产生相同的字符串。我们维护这样一个唯一字符串的列表,最后我们解码所有这样的字符串以打印其单独的元素。
以下是其实现方式–

C++
// C++ program to find all subsets of given set. Any
// repeated subset is considered only once in the output
#include 
using namespace std;
 
// Utility function to split the string using a delim. Refer -
// http://stackoverflow.com/questions/236129/split-a-string-in-c
vector split(const string &s, char delim)
{
    vector elems;
    stringstream ss(s);
    string item;
    while (getline(ss, item, delim))
        elems.push_back(item);
 
    return elems;
}
 
// Function to find all subsets of given set. Any repeated
// subset is considered only once in the output
int printPowerSet(int arr[], int n)
{
    vector list;
 
    /* Run counter i from 000..0 to 111..1*/
    for (int i = 0; i < (int) pow(2, n); i++)
    {
        string subset = "";
 
        // consider each element in the set
        for (int j = 0; j < n; j++)
        {
            // Check if jth bit in the i is set. If the bit
            // is set, we consider jth element from set
            if ((i & (1 << j)) != 0)
                subset += to_string(arr[j]) + "|";
        }
 
        // if subset is encountered for the first time
        // If we use set, we can directly insert
        if (find(list.begin(), list.end(), subset) == list.end())
            list.push_back(subset);
    }
 
    // consider every subset
    for (string subset : list)
    {
        // split the subset and print its elements
        vector arr = split(subset, '|');
        for (string str: arr)
            cout << str << " ";
        cout << endl;
    }
}
 
// Driver code
int main()
{
    int arr[] = { 10, 12, 12 };
    int n = sizeof(arr)/sizeof(arr[0]);
 
    printPowerSet(arr, n);
 
    return 0;
}


Python3
# Python3 program to find all subsets of
# given set. Any repeated subset is
# considered only once in the output
def printPowerSet(arr, n):
     
    # Function to find all subsets of given set.
    # Any repeated subset is considered only
    # once in the output
    _list = []
 
    # Run counter i from 000..0 to 111..1
    for i in range(2**n):
        subset = ""
 
        # consider each element in the set
        for j in range(n):
 
            # Check if jth bit in the i is set.
            # If the bit is set, we consider
            # jth element from set
            if (i & (1 << j)) != 0:
                subset += str(arr[j]) + "|"
 
        # if subset is encountered for the first time
        # If we use set, we can directly insert
        if subset not in _list and len(subset) > 0:
            _list.append(subset)
 
    # consider every subset
    for subset in _list:
 
        # split the subset and print its elements
        arr = subset.split('|')
        for string in arr:
            print(string, end = " ")
        print()
 
# Driver Code
if __name__ == '__main__':
    arr = [10, 12, 12]
    n = len(arr)
    printPowerSet(arr, n)
 
# This code is contributed by vibhu4agarwal


输出:

10 
12 
10 12 
12 12 
10 12 12 

请参阅下面的文章以使用回溯方法解决问题。

https://www.geeksforgeeks.org/backtracking-to-find-all-subsets/