c++|全排列算法

1. 一般输出(不按照字典序,只是简单全排列)

比如数组[1,2,3],一直固定第一位,对剩下的元素进行全排列(把不同的元素依次放到第一位。)
(1) 首先固定1,即1放到第一位,对后两个元素进行全排列;
(2) 固定2,即更换1与2的位置,数组变成[2,1,3],固定2,对[1,3]进行全排列;
(3) 交换1与3的位置,固定3,对[2,1]进行全排列。
本质上是一个递归问题。
需要注意的是,每一次更换完,全排列完以后,要将数组恢复,即再用一次swap函数,否则会有重复的交换,输出重复的排列情况。

#include
#include
#include
using namespace std;

void swap(char A[], int i, int j){
    char temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

void printArray(char A[], int n){
    int i;
    for(i = 0; i < n; i++)
        cout<>A[i];
    perm(A, 0, 2);
}

2. 按照字典序输出

①在main函数中拿到原序列以后,首先用sort函数将它字典序排列,比如从badcfe变成abcdef
②swap函数更改一下,比如一开始是序列为abcdef,交换a和d,我们不是简单的变成dbcaef,而是变成dabcef,这样可以保证下次递归时使用的是“abcef”这个按照字典序排列的子序列(数组的简单移动即可实现),这样除了第一位,后面的仍然是按照字典序。可以理解为把j位置的字符插入到i字符前面,i-j之间的的字符串都后移一位。e.g. swap("abcdef", 2, 5): abcdef -> abfcde
③swap函数的回溯也要重写一个swapback,让序列恢复到swap之前的状态

void Swap(int A [], int i, int j)
{
    int k,  temp;
    temp = A[j];
    for (k = j - 1; k >= i; k--) {
        A[k + 1] = A[k];
    }
    A[i] = temp;
}
// 将数组还原
void Swapback(int A [], int i, int j)
{
    int k, temp;
    temp = A[i];
    for (k = i + 1; k <= j; k++) {
        A[k - 1] = A[k];
    }
    A[j] = temp;
}

完整按照字典序的全排列算法如下:(这里将数组改成了字符数组)
需要注意的是排序函数的参数也必须是排好序的数组,即先用sort函数处理输入。

#include
#include
using namespace std;
 
void Swap(char A[], int i, int j)
{
    int k, temp;
    temp = A[j];
    // 从i到j,所有元素往后移一个,然后把最后一个元素A[j]放到第一位
    for (k = j - 1; k >= i; k--) {
        A[k + 1] = A[k];
    }
    A[i] = temp;
}
void Swapback(char A[], int i, int j)
{
    int k, temp;
    temp = A[i];
    // 从i到j,所有元素往前移一个,然后把第一个元素A[i]放到最后一位
    for (k = i + 1; k <= j; k++) {
        A[k - 1] = A[k];
    }
    A[j] = temp;
}
 
void printArray(char A[], int n){
    int i;
    for(i = 0; i < n; i++)
        cout<>str;
    int len = str.length();
    char A[len];
    for(int i = 0; i < len; i++)
        A[i] = str[i];
    sort(A,A+len);  
    perm(A, 0, len-1);
 
}

3. 用DFS解决全排列问题

例题
也可以用上述swap的来解决,这里给出另一种方法。

vector> res;
vector cur;
bool visit[10];

void DFS(vector nums){
    if(cur.size() == nums.size()){
        res.push_back(cur);
        return;
    }
    for(int i = 0; i < nums.size(); i++){
        if(visit[i]){
            continue;
        }
        cur.push_back(nums[i]);
        visit[i] = true;
        DFS(nums);
        cur.pop_back();
        visit[i] = false;
    }

}
vector> permute(vector& nums){
    DFS(nums);
    return res;
}

你可能感兴趣的:(c++|全排列算法)