全排列算法問題

ACM經典算法題目

輸入n,輸出1~n的全排列

如輸入:3

輸出:

123
132
……

如圖:

關於這個問題要如何實現呢:

大家可以自己先思考一下,下面我說一下答案。

這其實是一道簡單的深度優先搜索的題目

代碼:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;

#define MAX_N 1000

bool used[MAX_N];
int perm[MAX_N];

void permutation1(int pos, int n)
{
    if(pos == n)
    {
        for(int i = 0; i < n; i++)
        {
            printf("%d ", perm[i]);
        }
        printf("\n");
        return ;
    }
    for(int i = 0; i < n; i++)
    {
        if(!used[i])
        {
            perm[pos] = i;
            used[i] = true;
            permutation1(pos+1, n);
            used[i] = false;
        }
    }
    return ;
}

int main()
{
    int n;
    scanf("%d", &n);
    permutation1(1, n+1);
    return 0;
}

結果:

如果對代碼有問題的小夥伴我猜是對這一段代碼塊不理解

for(int i = 0; i < n; i++)
        {
            if(!used[i])
            {
                perm[pos] = i;
                used[i] = true;
                permutation1(pos+1, n);
                used[i] = false;
            }
        }

其實不難:設定一個used數組用來標記當前元素是否已經被訪問,如果沒有被訪問過則進入if代碼塊,將當前元素填入perm數組中(perm數組是用來記錄全排列元素的順序的)並將used數組置爲true,並遞歸調用此函數。那麼問題來了,爲什麼要在後面加一個把used數組又重置爲false呢?其實這就是dfs的回溯(相信有的小夥伴已經明白了)。比如:123下一個排列是132,爲什麼能產生132呢,就是因爲當本次遞歸到出口後,又將used數組重置爲false才能夠繼續訪問2和3,先重置元素3,再重置元素2,這就是回溯。

那麼到這裏還沒有結束,因爲c++標準庫爲我們提供了一種更加便捷的方式(記得要加頭文件algorithm):

代碼:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;

#define MAX_N 1000
int perm2[MAX_N];

void permutation2(int n)
{
    for(int i = 0; i < n; i++)
    {
        perm2[i] = i;
    }
    do{
        for(int i = 0; i < n; i++)
            printf("%d ", perm2[i]);
        printf("\n");
    }while(next_permutation(perm2, perm2+n));
    return ;
}

int main()
{
    int n;
    scanf("%d", &n);
    permutation2(n);
    return 0;
}

結果:

是不是感覺又輕鬆了不少呢!

發佈了59 篇原創文章 · 獲贊 45 · 訪問量 55萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章