全排列

作者: 无聊的学习中 | 来源:发表于2016-07-17 01:28 被阅读0次

    发现一直以来我写全排列的方法似乎有点山寨,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]);
        }
    }
    

    相关文章

      网友评论

          本文标题:全排列

          本文链接:https://www.haomeiwen.com/subject/oqiujttx.html