1. 程式人生 > >每天一個演算法: 全排列演算法

每天一個演算法: 全排列演算法

全排列演算法:給出一個有n個元素的集合,求出這個集合所有可能的排列。
一、 遞迴的方法

void  permutation(char *arr, int k , int m){
     if(k == m){
        for(int i =0; i< m; i++){
            cout<<arr[i];    //輸出排列                    
        }
        cout<<endl;
     }else {
        for(int j = k; j < m; j++){
            swap(arr[j],arr[k]);
            permutation(arr,k+1
,m); swap(arr[j],arr[k]); } } }

二、 STL實現
有時候遞迴的效率使得我們不得不考慮除此之外的其他實現,很多把遞迴演算法轉換到非遞迴形式的演算法是比較難的,這個時候我們不要忘記了標準模板庫已經實現的那些演算法,這讓我們非常輕鬆。STL有一個函式next_permutation(),它的作用是如果對於一個序列,存在按照字典排序後這個排列的下一個排列,那麼就返回true且產生這個排列,否則返回false。注意,為了產生全排列,這個序列要是有序的,也就是說要呼叫一次sort。STL提供的next_permutation()函式大大簡化了程式設計,這是一個十分有用的函式。此外與之對應的還有prev_permutation()函式,可以得到上一個全排列。這讓全排列實現起來很簡單,我們看一下程式碼:

    void permutation(char* str,int length)  
{  
    sort(str,str+length);  
    do  
    {  
        for(int i=0;i<length;i++)  
            cout<<str[i];  
        cout<<endl;  
    }while(next_permutation(str,str+length));  

}  

三、有一定約束條件的全排列
對數1,2,3,4,5要實現全排序。要求4必須在3的左邊,其它的數位置隨意。思路:首先使用上面的2種方法之一實現全排列,然後對全排列進行篩選,篩選出4在3左邊的排列。

void permutation(int* a,int length)  
{  
    int i,flag;  
    sort(a,a+length);  
    do  
    {  
        for(i=0;i<length;i++)  
        {  
            if(a[i]==3)  
                flag=1;  
            else if(a[i]==4)    //如果3在4的左邊,執行完程式碼,flag就是2  
                flag=2;  
        }  
        if(flag==1)          //如果4在3的左邊,執行完程式碼,flag就是1  
        {  
            for(i=0;i<length;i++)  
                cout<<a[i];  
            cout<<endl;  
        }  
    }while(next_permutation(a,a+length));  

}

四: next_permutation的原理
next_permutation()函式是按照字典序的順序得出比當前排列大,且最靠近當前排列的下一個排列。
函式實現原理如下:在當前序列中,從尾端往前尋找兩個相鄰元素,前一個記為*i,後一個記為*ii,並且滿足*i < *ii。然後再從尾端尋找另一個元素*j,如果滿足*i < *j,即將第i個元素與第j個元素對調,並將第ii個元素之後(包括ii)的所有元素顛倒排序,即求出下一個序列了。程式碼如下:

template<class BidirectionalIterator>  
bool next_permutation(  
      BidirectionalIterator first,   
      BidirectionalIterator last  
)  
{  
    if(first == last)  
        return false; //空序列  

    BidirectionalIterator i = first;  
    ++i;  
    if(i == last)  
        return false;  //一個元素,沒有下一個序列了  

    i = last;  
    --i;  

    for(;;) {  
        BidirectionalIterator ii = i;  
        --i;  
        if(*i < *ii) {  
            BidirectionalIterator j = last;  
            while(!(*i < *--j));  

            iter_swap(i, j);  
            reverse(ii, last);  
            return true;  
        }  

        if(i == first) {  
            reverse(first, last);  //全逆向,即為最小字典序列,如cba變為abc  
            return false;  
        }  
    }  

}  

相關推薦

每天一個演算法 排列演算法

全排列演算法:給出一個有n個元素的集合,求出這個集合所有可能的排列。 一、 遞迴的方法 void permutation(char *arr, int k , int m){ if(

一個簡單的排列演算法

什麼是全排列?就是從n個數字中選擇n個數字按照一定的順序排列起來。 本文要討論的演算法要完成的任務是:給定一個數組,輸出其所有的全排列結果。要求可以概括為兩點: 輸出該陣列所有的全排列結果 任意兩個全排列是不同的,即任意兩個全排列中n個數字排列的順序不能相同

程式設計藝術第十六~第二十章排列/跳臺階/奇偶調序,及一致性Hash演算法

第十六~第二十章:全排列,跳臺階,奇偶排序,第一個只出現一次等問題作者:July、2011.10.16。出處:http://blog.csdn.net/v_JULY_v。引言    最近這幾天閒職在家,一忙著投簡歷,二為準備面試而蒐集整理各種面試題。故常常關注個人所建的Alg

LeetCode演算法題47排列 II解析

給定一個可包含重複數字的序列,返回所有不重複的全排列。 示例: 輸入: [1,1,2] 輸出: [ [1,1,2], [1,2,1], [2,1,1] ] 這個題和上一個題全排列是一樣的,只是在判斷條件中在加一些防止重複元素重複出現的元素就可以了。這裡加到最裡面。

LeetCode演算法題46排列解析

給定一個沒有重複數字的序列,返回其所有可能的全排列。 示例: 輸入: [1,2,3] 輸出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 這個題突然讓我又對遞迴產生了新的認識,遞迴可以

一個排列演算法

從1到N,輸出全排列,共N!條。 分析:用N進位制的方法吧。設一個N個單元的陣列,對第一個單元做加一操作,滿N進 一。每加一次一就判斷一下各位陣列單元有無重複,有則再轉回去做加一操作,沒 有則說明得到了一個排列方案。

演算法02排列字典序演算法

(2)字典序法 對於數字1、2、3......n的排列,不同排列的先後關係是從左到右逐個比較對應的數字的先後來決定的。如{1,2,3}的排列中,132排在123之後,排在213之前。 演算法思路: 1.如對於{1,2,3,4,5}的一個排列p1為list[]={1,3,

演算法01排列遞迴演算法

全排列是指n個元素按一定順序的所有排列組合,如{1,2,3}三個元素的全排列為{1,2,3}、{1,3,2}、{2,1,3}、{2,3,1}、{3,1,2}、{3,2,1}共3!種。 常見排列的演算法一般有: (1)遞迴法 (2)字典序法 (3)鄰位對換法 (4)遞增進位

dfs 排列演算法(含重複元素)

1、數的全排列 求數字 1 ~ n 的全排列,例如 1~3 的全排列,輸出 1 2 3, 1 3 2 , 2 1 3, 2 3 1, 3 1 2, 3 2 1 #include<bits/stdc++.h> using namespace std; #define runfil

演算法基礎】字串的排列演算法

題目描述 輸入一個字串,按字典序打印出該字串中字元的所有排列。例如輸入字串abc,則打印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。 輸入描述 輸入一個字串,長度不超過9(可能有字元重複),字元只包括大小寫字母。 這道題是劍指offfer中一道

排列演算法(使用遞迴)

問題描述    對於任意的n個字母,實現其的全排列,並查詢第m個,其排列形式。我寫的這個程式碼中主要用的遞迴。 程式碼如下 #include<stdio.h>int n,book[10],k;      &nbs

牛客網 之 數列還原(數列的排列演算法

題目描述 牛牛的作業薄上有一個長度為 n 的排列 A,這個排列包含了從1到n的n個數,但是因為一些原因,其中有一些位置(不超過 10 個)看不清了,但是牛牛記得這個數列順序對的數量是 k,順序對是指滿足 i < j 且 A[i] < A[j] 的對

原創非遞迴實現排列演算法

Python語言描述 空間換時間的做法,藉助佇列去實現全排列 # ---------藉助佇列去實現全排列(原創)--------- from copy import copy class Per_node(object): def __init__(self,el

排列演算法遞迴實現

前言: 在一些演算法題當中有時需要進行全排列,是一個比較簡單的遞迴呼叫,在這裡記錄下,以後可以直接拿來使用。 過程: 例如{1,2,3,4,5}: 第一步: {1}和{2,3,4,5}的全排列組合; {2}和{1,3,4,5}的全排列組合; {3}和{2,1,4,5}的全排列組合; …

演算法練習-- C# DFS 排列演算法

void Main() { var r = A(new List<string>(){"a","b","c","d","e","f"}); Console.WriteLine(r.Cou

紫書第七章-----暴力求解法(排列演算法

遞迴求全排列 /* 本程式是遞迴實現全排列演算法。 思想是分別讓誰打頭。以1,2,3,4為例,一共只有4位, 第一位可以分別讓1,2,3,4打頭,以第一位是1為例, 第二位可以分別讓2,3,4打頭,以第二位是2為例,

排列演算法及其C++實現(轉)

第十六章、全排列問題53.字串的排列。題目:輸入一個字串,打印出該字串中字元的所有排列。例如輸入字串abc,則輸出由字元a、b、c 所能排列出來的所有字串abc、acb、bac、bca、cab 和cba。    分析:此題最初整理於去年的微軟面試100題中第53題,第二次整理於微軟、Google等公司非常好的

排列演算法(字典序法、SJT Algorithm 、Heap's Algorithm)

一、字典序法 1) 從序列P的右端開始向左掃描,直至找到第一個比其右邊數字小的數字,即。 2) 從右邊找出所有比大的數中最小的數字,即。 3) 交換與。 4) 將右邊的序列翻轉,即可得到字典序的下一個排列。 5) 重複上面的步驟,直至得到字典序最大的排列,即左邊數字比右邊的

動態規劃DP演算法實現排列

/* * 全排列  * 無相同元素 * 1. 取第1個元素插入空字串, 1種情況  * 2. 取第2個元素插入長度為1的字串, 1*2 = 2種情況, 例如 'b'插入"a",可以在'a'前, 'a'後  * 3. 取第3個元素插入長度為2的字串, 2*3 = 6種情況, 例

排列演算法c++實現

問題: Given a collection of numbers, return all possible permutations. For example, [1,2,3] have the following permutations: [1,2,3], [1,3