编程挑战(6)
组合算法:开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标代表的数被选中,为0则没有选中。
首先初始化,将数组前n个元素置1,表示第一个组合为前n个数;然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端;当第一个“1”移动到数组的m-n位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。
例如求5中选3的组合:
1 1 1 0 0 //1, 2, 3
1 1 0 1 0 //1, 2, 4
1 0 1 1 0 //1, 3, 4
0 1 1 1 0 //2, 3, 4
1 1 0 0 1 //1, 2, 5
1 0 1 0 1 //1, 3, 5
0 1 1 0 1 //2, 3, 5
1 0 0 1 1 //1, 4, 5
0 1 0 1 1 //2, 4, 5
0 0 1 1 1 //3, 4, 5
void output1(int value[], char* middle, int length) { for(int i=0; i<length; i++) { if(middle[i] == '1') { printf("%d ", value[i]); } } printf("\n"); } bool find10(char* middle, int M, int* index) { bool find = false; for(int i=0; i<M; i++) { if (middle[i] == '1' && middle[i + 1] == '0') { *index = i; find = true; break; } } return find; } void move1(char* middle, int index) { int count = 0; for(int i=0; i<index; i++) { if (middle[i] == '1') { swap(middle[count++], middle[i]); } } } //从M 个数中取 N 个数的组合 void enumkind(int value[], int M, int N) { char *middle = new char[M + 1]; middle[M] = '\0'; memset(middle, '1', N); memset(middle + N, '0', M - N); printf("%s: ", middle); output1(value, middle, M); int index = 0; while(find10(middle, M, &index)) { swap(middle[index], middle[index+1]); move1(middle, index); printf("%s: ", middle); output1(value, middle, M); } delete middle; } int _tmain(int argc, _TCHAR* argv[]) { int value[5] = {1,2,3,4,5}; enumkind(value, sizeof(value)/sizeof(int), 4); getchar(); return 0; }