Two methods are used to evaluate all subsets of a set, and two methods are used to calculate subsets of a set.
Suppose we have a requirement to evaluate all the subsets of a set (including the set itself), that is, there is a set s, which contains two elements <a, B>, then all the subsets are <a, AB, B>.
It is not difficult to obtain. The relationship between the subset sn and the number n of the original set elements is: sn = 2 ^ n-1.
This article describes two implementation methods:
I. Bitmap method:
1) construct an array A of the same size as the set, which corresponds to an element in the set. The elements in array A have only two states: "1" and "0 ", indicates whether the corresponding elements in the current set are output in each subset output. In this way, array A can be regarded as A mark bitmap of the original set.
2) array A simulates the integer "add one" operation. After each "add one" operation, all elements in the original set that correspond to the value of array A as "1" are output.
Set the original set to <a, B, c, d>. The status of array A after a "plus one" operation is [,]. the subset of this output is <a, c, d>.
The Code is as follows:
/* The non-recursive idea is used. If there is an array whose size is n, then the n-bit binary will be used. If the corresponding bit is 1, the output will be less than if the corresponding bit is 0. output this bit * // * use the bitmap idea to construct a single bit set with the same size as the array, if the corresponding bit in the bitmap is 1, the elements in the array can be output. If the corresponding bit in the bitmap is 0, the corresponding bit in the array does not output the array used to simulate the bitmap, here the focus is to simulate the array plus 1 operation * // * use the array to simulate bitmap plus 1 operation array can always add 1 until all elements in the array are 1 function return value is bool array Initialization the highest bit is 1 */# define MAX_LEN 10 void bitmap (char str [], const int n) {bitset <MAX_LEN> count; wang. set (); int I = 0; unsigned long value = wang. to_ulong (); cout <wang <"<value <endl; int count = 0; while (value) {bitset <MAX_LEN> bit (value --); for (I = 0; I <bit. size (); I ++) if (bit [I]) cout <str [I]; cout <endl; count ++ ;} cout <count <endl ;}
3) time complexity: O (n * 2 ^ n ). In fact, the program can be further optimized during the process of traversing the output subset. For example, in the m iteration, you only need to traverse the first k elements, k = log2 (m) + 1. In this way, without considering the array simulation "plus one" operation, the total number of traversal is Sn = (n-2) * 2 ^ n + 2, n> = 2; Sn = 1, n = 1. Although the complexity remains unchanged, the total running time will be reduced.
4) spatial complexity: each iteration of the method is independent and has no relationship with the results of the previous iteration. Therefore, the memory can be reused after each output subset. You only need an array of the same size as the original set. The space complexity is O (n ).
Ii. Recursive iteration:
1) recursive iteration is adopted. The specific process is as follows,
Set, the original set s = <a, B, c, d>, and the subset result is r:
First iteration:
R = <a>
The second iteration:
R = <a AB B>
The third iteration:
R = <a AB B ac abc bc c>
Fourth iteration:
R = <a AB B ac abc bc c ad abd bd acd abcd bcd d>
Each iteration is the result of the previous iteration + each element in the result of the previous iteration adds the element of the current iteration + the element of the current iteration.
The Code is as follows:
/* The above method cannot be used to understand the recursive idea. The next step is to output the characters in the back. The subset of this output is the subset of the previous output + the elements of this iteration * /# if 1 void print (char * str) {/* uses two arrays, one record the results of the previous iteration one record the results to be output this time the vec record is the subset back record to be referenced in the next iteration is to generate a new subset after the vec iteration */int count = 0; vector <char> vec; vector <char> back; int j; for (int I = 0; I <strlen (str); I ++) {if (I = 0) {vec. push_back (str [I]); vec. push_back (','); back = vec;} else {for (j = 0; j <back. size (); j ++) if (back [j] = ',') {back. insert (back. begin () + j, str [I]); j ++;} back. push_back (str [I]); back. push_back (',');} for (j = 0; j <back. size (); j ++) {if (back [j] = ',') {printf ("\ r \ n"); count ++ ;} elseprintf ("% c", back [j]); if (I) vec. push_back (back [j]);} back = vec;} printf ("sub_set count is % d \ r \ n", count);} # endif
2) time complexity
According to the above process, it is not hard to find, the number of iterations of the k iteration is: 2 ^ K-1. N> = k> = 1, n iterations, total traversal times: 2 ^ (n + 1)-(2 + n), n> = 1.
The time complexity is O (2 ^ n ).
3) space complexity
Because of this algorithm, the results of the last iteration are required for the next iteration, and there is no next iteration after the last iteration. Therefore, if the original set has n elements, the total number of subsets to be saved in the iteration process is 2 ^ (n-1)-1, n> = 1. Note that the number of subsets is considered here, and the length of each subset element is regarded as 1.
Summary:
Recursion is very time-consuming, because it is recursion. In the first method, bitset in C ++ is used. This method is very efficient. In the second method, the purpose of using two vectors is that one vector records the set to be output in this iteration, And the other vector records the output in the previous iteration.
Number of subsets of a set
You can back the formula
If there are n elements in a set, its subset has the n power of 2 (note the existence of the empty set ),. A non-empty subset has two n minus one, a real subset has two n minus one, and a non-empty real subset has two n minus two.
If there are few elements, you can use the enumeration method.
However, the best method is to use the binary theorem.
For example
Contains n elements in a collection (the following C represents a combination, where nCr indicates selecting r elements from n elements for combination)
First, the subset contains 0 elements, including [nC0].
One subset element has [nC1]
The subset element has two [nC2]
......
Subset elements with m [nCm]
......
There are n-1 subset elements and [nC (n-1)]
Subset elements have n [nCn]
Therefore, a finite set contains [nC0] + [nC1] + [nC2] + ...... + [NCm] + ...... + [NC (n-1)] + [nCn]
According to the binary Theorem
Zhi [nC0] + [nC1] + [nC2] + ...... + [NCm] + ...... + [NC (n-1)] + [nCn] = 2 ^ n
How to calculate the number of subsets of a set, such as all subsets of {1, 2, 3, 4, 5, 6? (Simple Method)
The number of subsets of any finite set is 2 ^ n;
The number of all subsets of {1, 2, 3, 4, 5, 6} is 2 ^ 6 = 64