记录一种从n个数中取m个数进行排列的方法(0-1枚举)

    xiaoxiao2023-11-09  160

    摘要

    将n个数字放到一个长度为n的数组中。
    再生成一个长度为n的0-1数组,1代表选取该位置映射的元素,0代表不选取(1的总数等于m),通过枚举0 1的所有位置,来完成数字组合的枚举。

    具体枚举逻辑:

    令0-1数组所有元素都为0

    令0-1数组前m个元素都为1(此时就已经代表了一种组合)

    循环切换:

    利用for找到该0-1数组第一个存在“1 0”的位置(即前一位置为1,后一位置为0),对调两者位置(变为0 1),再将该位置之前的所有1移动到数组最左边。 此时完成一次新组合。

    当数组中的m个一,连续排放在该z数组的最右边的,就是最后一次组合,结束循环。

    实例:

    例如求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

    代码(未整理,但其中做了01转换)

    int compare(int this_value, int new_ar[], int new_len) {//输入当前目标值,输入去除该值后的数组,给出新数组长度,返回该值是否可以被数组中两个数累加 int this_sum, counter; int *bl = new int[new_len]; counter = 0; for (int i = 0; i < new_len; i++) bl[i] = 0; bl[0] = 1; bl[1] = 1; while (1) { this_sum = 0; for (int i = 0; i < new_len; i++) if (bl[i] == 1) this_sum += new_ar[i]; if (this_sum == this_value) {//如果满足了,break counter = 1; break; } if (bl[new_len - 1] == 1 && bl[new_len - 2] == 1) break; //如果刚刚做的是最后一次组合,break //生成下一次组合 int i0; for (i0 = 0; i0 < new_len; i0++) //找出第一个10,对调 if (bl[i0] == 1 && bl[i0 + 1] == 0) { bl[i0] = 0; bl[i0 + 1] = 1; break;//第一个10,发现位置的索引就是此时i0 } for (int i1 = 0, i2 = 0; i1 < i0; i1++) {//将i0前面的1全部放到开头, if (bl[i1] == 1) {//原来的位置改0,从开头把1放过去 bl[i1] = 0; bl[i2++] = 1; } } }
    最新回复(0)