Anche se è una domanda poco vecchia e ha già risposto pensato di aggiungere i miei input per aiutare i nuovi visitatori. Prevede anche di spiegare il tempo di esecuzione senza concentrarsi sulla riconciliazione ricorsiva.
Ho scritto l'esempio in C# ma è facile da capire per la maggior parte dei programmatori.
static int noOfFunctionCalls = 0;
static int noOfCharDisplayCalls = 0;
static int noOfBaseCaseCalls = 0;
static int noOfRecursiveCaseCalls = 0;
static int noOfSwapCalls = 0;
static int noOfForLoopCalls = 0;
static string Permute(char[] elementsList, int currentIndex)
{
++noOfFunctionCalls;
if (currentIndex == elementsList.Length)
{
++noOfBaseCaseCalls;
foreach (char element in elementsList)
{
++noOfCharDisplayCalls;
strBldr.Append(" " + element);
}
strBldr.AppendLine("");
}
else
{
++noOfRecursiveCaseCalls;
for (int lpIndex = currentIndex; lpIndex < elementsList.Length; lpIndex++)
{
++noOfForLoopCalls;
if (lpIndex != currentIndex)
{
++noOfSwapCalls;
Swap(ref elementsList[currentIndex], ref elementsList[lpIndex]);
}
Permute(elementsList, (currentIndex + 1));
if (lpIndex != currentIndex)
{
Swap(ref elementsList[currentIndex], ref elementsList[lpIndex]);
}
}
}
return strBldr.ToString();
}
static void Swap(ref char Char1, ref char Char2)
{
char tempElement = Char1;
Char1 = Char2;
Char2 = tempElement;
}
public static void StringPermutationsTest()
{
strBldr = new StringBuilder();
Debug.Flush();
noOfFunctionCalls = 0;
noOfCharDisplayCalls = 0;
noOfBaseCaseCalls = 0;
noOfRecursiveCaseCalls = 0;
noOfSwapCalls = 0;
noOfForLoopCalls = 0;
//string resultString = Permute("A".ToCharArray(), 0);
//string resultString = Permute("AB".ToCharArray(), 0);
string resultString = Permute("ABC".ToCharArray(), 0);
//string resultString = Permute("ABCD".ToCharArray(), 0);
//string resultString = Permute("ABCDE".ToCharArray(), 0);
resultString += "\nNo of Function Calls : " + noOfFunctionCalls;
resultString += "\nNo of Base Case Calls : " + noOfBaseCaseCalls;
resultString += "\nNo of General Case Calls : " + noOfRecursiveCaseCalls;
resultString += "\nNo of For Loop Calls : " + noOfForLoopCalls;
resultString += "\nNo of Char Display Calls : " + noOfCharDisplayCalls;
resultString += "\nNo of Swap Calls : " + noOfSwapCalls;
Debug.WriteLine(resultString);
MessageBox.Show(resultString);
}
Passi: Per esempio quando passiamo input come "ABC".
- Metodo di permessi chiamato da Principale per la prima volta. Quindi chiamare con l'indice 0 e questa è la prima chiamata.
- Nella parte else di loop for ripetiamo da 0 a 2 effettuando 1 chiamata ogni volta.
- Sotto ogni ciclo, stiamo chiamando ricorsivamente con LpCnt + 1. 4.1 Quando l'indice è 1 quindi 2 chiamate ricorsive. 4.2 Quando l'indice è 2 quindi 1 chiamate ricorsive.
Quindi dal punto 2 al 4.2 le chiamate totali sono 5 per ogni ciclo e il totale è di 15 chiamate + chiamata di ingresso principale = 16. Ogni volta che loopCnt è 3 allora se la condizione viene eseguita.
Dal diagramma si può vedere il conteggio dei loop che diventa 3 totale 6 volte, vale a dire il valore del fattore di 3 cioè la lunghezza di "ABC" di ingresso.
Se l'istruzione per il ciclo si ripete 'n' volte per visualizzare caratteri dall'esempio "ABC", ad esempio 3. Totale 6 volte (Tempi fattoriali) in cui immettere se visualizzare le permutazioni. Quindi il tempo di esecuzione totale = n X n !.
Ho dato alcune variabili CallCnt statiche e la tabella per capire ogni esecuzione di riga in dettaglio.
Esperti, sentitevi liberi di modificare la mia risposta o commento se qualcuno dei miei dettagli non è chiaro o errato, sono felice correggerli.
Download the sample code and other samples from here
Prova a disegnare fuori su carta, oppure si può anche provare a singolo passo il codice in un debugger. –
Aggiunta per alcuni nuovi: [Scrivi un programma C per stampare tutte le permutazioni di una determinata stringa] (http://www.geeksforgeeks.org/write-ac-program-to-print-all-permutations-of-a- stringa data /) –
La prima cosa è che la ricorsione solo a volte si traduce in soluzioni eleganti e intuitive. A volte la soluzione è elegante ma non per niente intuitiva, come credo sia qui. A volte non è né elegante, né intuitivo. Potrebbe esserci qualcosa di inelegante ma intuitivo? Non lo so. In questo caso la prima cosa che devi capire, concettualmente, è come creare tutte le permutazioni scambiando varie coppie di elementi nella matrice. Quindi devi capire come viene applicato l'algoritmo ricorsivo per realizzare questo concetto. Può aiutare a disegnare l'albero di ricorsione su carta ad ogni passaggio. – broadbear