第一种方法就是先不断到加元素,然后再考虑删去一个元素,再加一个新到元素进来
1 void print_subset(int n,int A[],int cur) { 2 for (int i=0;i<cur;i++) 3 printf("%d ",A[i]); 4 printf(" "); 5 int s = cur ? A[cur-1]+1 : 0; 6 for (int i=s;i<n;i++) { 7 A[cur] = i; 8 print_subset(n,A,cur+1); 9 }
第二种方法就更好理解了,就是对于每个元素我们都有两种情况(取和不取)
1 void print_Subset(int n,int B[],int cur) { 2 if (cur == n) { 3 for (int i=0;i<cur;i++) { 4 if (B[i]) 5 printf("%d ",i); 6 } 7 printf(" "); 8 return ; 9 } 10 B[cur] = 1; 11 print_Subset(n,B,cur+1); 12 B[cur] = 0; 13 print_Subset(n,B,cur+1); 14 }
第三种方法 二进制!
二进制的方法很简单,其实就是把二进制的 0 和 1 当成一个 “开关”。1 代表选取,0 代表不选。
其实二进制的每一位其实对应的是我们所给数组的下标的映射(我个人理解是这样的)
求长度为 n 的并且是从0~n-1 的连续数组的子集
1 void print_subset(int n,int s) { 2 for (int i=0;i<n;i++) { 3 if (s & (1<<i)) 4 printf("%d ",i); 5 } 6 printf(" "); 7 }
求长度为 n 的任意的数组的子集 如果理解了我前面说的二进制是对数组下标的一个映射,这个就很简单
1 int a[3] = {5, 4, 6}; 2 3 void print_subset(int n,int s) { 4 for (int i=0;i<n;i++) { 5 if (s & (1<<i)) 6 printf("%d ",a[i]); 7 } 8 printf(" "); 9 }