全排列

发现一直以来我写全排列的方法似乎有点山寨,2333
正规点的应该是,对于序列a[i..m],第i个地方的的值可以是a[i..m]中的任意一个,于是枚举k = i..m,
然后交换a[i], a[k],然后递归下去

void perm(int a[], int l, int r) {
    if (l == r) {
        for (int i = 0; i < r; i++) {
            printf("%d ", a[i]);
        }
        printf("\n");
        return ;
    }
    for (int i = l; i < r; i++) {
        swap(a[l], a[i]);
        perm(a, l + 1, r);
        swap(a[l], a[i]);
    }
}

简单的说i位置的元素就是剩下的元素里面选一个嘛,没啥问题。

然后呢,如果有重复元素咋办呢?按照我以前的山寨写法就要去重了,按内存开销可大了。
其实很简单,对于a[i]我们在剩下的里面选,重复的只选一次不就行了!所以呢,每次选的时候我们判断一下当前选的a[k],在a[i..k-1]里面是否出现过,如果出现过,说明a[i]这个位置我们已经选过a[k]这个值了,不用再重复选择了。

bool check(int a[], int l, int r) {
    for (int i = l; i < r; i++) {
        if (a[i] == a[r]) {
            return false;
        }
    }
    return true;
}
void perm(int a[], int l, int r) {
    if (l == r) {
        for (int i = 0; i < r; i++) {
            printf("%d ", a[i]);
        }
        printf("\n");
        return ;
    }
    for (int i = l; i < r; i++) {
        if (!check(a, l, i)) {
            continue;
        }
        swap(a[l], a[i]);
        perm(a, l + 1, r);
        swap(a[l], a[i]);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容