首页 > 解决方案 > 在 C 中进行 4 个字母排列的最简单方法

问题描述

我需要编写一个返回类似这样的函数,只给出“1234”:

    char *permutations[] = {"1234","1324", "1342","1423","1432","2134",
                            "2143","2314","2341","2413","2431","3124","3142",
                            "3214","3241","3412","3421","4123","4132","4213",
                            "4231","4312","4321", "1243"};

我在标题中写了“字母”,因为我实际上需要这些数字是字符。我在这里阅读了各种帖子,但是它们都非常复杂,因为它们试图获取 N 个字母字符串的排列。我不需要那个,我只需要这些组合,但对如何做到这一点一无所知。我知道我应该告诉我我尝试了什么,但我真的什么都没有,因为我尝试过的所有代码都启发了使用概念,我完全不熟悉回溯和递归。有没有一种真正“简单”的方法可以在不使用任何库的情况下做到这一点?希望您能理解,我提前非常感谢大家。

标签: c

解决方案


这是一个例子:

A.第一个数字有 4 个可能的值,我们只是在外循环中遍历它们。

B.在外循环的每次通过时,第二个也是如此,除了我们避免重复 A 以使循环的长度为 3。

C.对于循环长度为 2 的 C 也是如此,因为它避免了重复 A 和 B。

D.最后一个值有一个唯一的选择,我们可以这样找到它:D = 10 - (A + B + C),其中 10 = 1+2+3+4。

每次找到一个新的 D 时,我们都会收集四个数字的序列,最终得到一个长度为 24 的排序序列。

static inline char increase(char c) { return (c - '0') % 4 + '1'; }
#define A seq[0]
#define B seq[1]
#define C seq[2]
#define D seq[3]

int main() 
{
    char seq[5] = { '0', '0', '0', '0', 0};
    char collector[24][5];
    char icollect = 0;
    //--- A
    for (char i = 0; i<4; i++) {
        A = increase(A);
        //---- B
        B = '0';
        for (char j = 0; j<3; j++) {
            B = increase(B);
            //---- C
            C = '0';
            if (B == A) B = increase(B);
            for (char k = 0; k<2; k++) {
                do { C = increase(C); } while (C == A || C == B);
                //---- D
                D = 10 - ((A - '0') + (B - '0') + (C - '0')) + '0';
                //Collects
                memcpy(collector[icollect++], seq, 5);
            }
        }
    }
    //Prints
    for (char i=0; i<24; i++) {
        printf("%s%c", collector[i], i && (i+1)%6==0 ? '\n' : ' ');
    }
}

/* printed
1234 1243 1324 1342 1423 1432
2134 2143 2314 2341 2413 2431
3124 3142 3214 3241 3412 3421
4123 4132 4213 4231 4312 4321
*/

推荐阅读