Algoritmo di combinazione: stampa tutte le possibili combinazioni di R
โก Riepilogo intelligente
L'algoritmo di combinazione stampa ogni possibile selezione di r elementi da un insieme di n, dove l'ordine non ha importanza. Questa risorsa spiega la formula di combinazione, la complessitร temporale, due metodi ricorsivi, la gestione dei duplicati e il codice C completo. C++e Python implementazioni.

Qual รจ la combinazione?
La Combinazione รจ una sorta di disposizione di alcuni oggetti dati. In termini matematici, la Combinazione รจ un insieme di scelte/selezione di elementi da un insieme unico di elementi/oggetti. Qui l'ordine degli articoli non ha importanza. ร noto anche come metodo per calcolare il risultato totale di un evento, in cui l'ordine del risultato non ha importanza.
Ad esempio, ti viene data una borsa con 5 colori diversi e ti viene chiesto di generare un motivo con 3 colori qualsiasi. Puoi anche scegliere 3 colori qualsiasi su 4, quindi disporli in ordini diversi.
Supponiamo che i colori siano RGYBI(R= Rosso, G= Verde, Y= Giallo, B= Blu, I= Indaco). Quindi, il modello possibile puรฒ essere RGB, RGY, ecc.
Diamo un'occhiata alla figura seguente:

Spiegazione:
- Prendi 4 colori qualsiasi su 5 ed elencali
- Da ogni blocco di 4 colori, scegline 3 e elencale tutte. Ad esempio, nella figura abbiamo scelto solo "RGBI" e mostrato 4 combinazioni.
- Dietro c'รจ una teoria per calcolare il numero totale di combinazioni che possiamo realizzare. Una combinazione di r elementi su n puรฒ essere matematicamente presentata come:
il segno "!" significa che fattoriale. Per esempio,
N! = N * (N-1) * (N-2) * โฆ * 3 * 2 * 1
Diciamo 5! = 5*4*3*2*1 = 120
Quindi, per il nostro problema di cui sopra, abbiamo 5 colori che significano n = 5 e, in qualsiasi momento, dobbiamo sceglierne 3 qualsiasi. Quindi, r = 3. Dopo il calcolo, otteniamo:
Per lo scenario sopra riportato sono possibili un totale di 10 combinazioni di colori.
Analisi della complessitร temporale per la combinazione
Ora, supponiamo che, dato un array di dimensione n, ci venga chiesto di prendere r elementi dall'array ed eseguire combinazioni di r elementi.
Se viene fornito un array di dimensione n, allora occorrerร O(n2) tempo per eseguire l'attivitร . Inoltre, se vogliamo rimuovere la voce duplicata, allora,
Dobbiamo eseguire i seguenti passaggi:
Passo 1) Ordina i dati dell'array di input in modo ascendente. La complessitร temporale dell'ordinamento รจ O(n*log(n)).
Passo 2) Crea un altro array contenente un elemento univoco dai dati dell'array temporaneo fornito.
Passo 3) Quindi, eseguire la funzione di combinazione.
Quindi, la complessitร temporale totale diventa = Sopra2) + O(nLog(n)). Possiamo considerarlo O(n2), come n2 รจ molto piรน grande di n*log(n).
Metodo 1: elemento fisso con ricorsione
In questo metodo, sceglieremo un elemento e poi troveremo una combinazione di r-1 elementi. Poichรฉ selezioniamo un elemento dal resto dell'elemento, lo facciamo in modo ricorsivo, ed รจ per questo che si chiama elemento fisso e ricorsione.
Dimostriamo l'algoritmo passo dopo passo con un diagramma:
I passaggi sono indicati di seguito:
Passo 1) Nel primo strato, prendi n-r+1 elementi. Ciรฒ significa che abbiamo preso 3 elementi.
Passo 2) Scegli un elemento dal 2ยฐ strato e portalo al nr. Quindi, se prendiamo โRโ, allora con R possiamo prendere G, Y e B.
Passo 3) Scegli un elemento dal 3ยฐ strato e portalo fino all'ennesimo elemento e forma blocchi contenenti 3 elementi ciascuno.
La figura sopra รจ il valore restituito dalla ricorsione. Verrร stampato solo l'ultimo strato.
Soprannome Code
function combination: pass in: inputArray, combinationArray, start, end, index, r if index is equal to r: for each element in combinationArray: print each element return for i = start: if i <=end and end -i+1 > r-index: combinationArray[index] = inputArray[i] call combination function again with updated parameter
Implementazione in C/C++
#include<bits/stdc++.h> #include<stdio.h> void Combination(char inputArray[], char combinationArray[], int start, int end, int index, int r) { if (index == r) { for (int i = 0; i < r; i++) { printf("%c", combinationArray[i]); } printf("\n"); return; } for (int i = start; i <= end && end - i + 1 >= r - index; i++) { combinationArray[index] = inputArray[i]; Combination(inputArray, combinationArray, i + 1, end, index + 1, r); } } int main() { char inputArray[] = {'R','G','Y','B','I'}; int n = sizeof(inputArray) / sizeof(inputArray[0]); int r = 3; char combinationArray[r]; printf("Combinations:\n"); Combination(inputArray, combinationArray, 0, n - 1, 0, r); }
Produzione:
Combinations: RGY RGB RGI RYB RYI RBI GYB GYI GBI YBI
implementazione in Python
def Combination(inputArray, combinationArray, start, end, index, r): if index == r: for item in combinationArray: print(item, end = " ") print() return i = start while (i <= end and end - i + 1 >= r - index): combinationArray[index] = inputArray[i] Combination(inputArray, combinationArray, i + 1, end, index + 1, r) i += 1 inputArray = "RGYBI" n = len(inputArray) r = 3 combinationArray = [0] * r Combination(inputArray, combinationArray, 0, n - 1, 0, r)
Produzione:
R G Y R G B R G I R Y B R Y I R B I G Y B G Y I G B I Y B I
Metodo 2 (Includi ed escludi ogni elemento)
Questo metodo si basa sull'identitร di Pascal. In precedenza abbiamo utilizzato la ricorsione per calcolare nCr. Qui, il metodo รจ semplicemente diviso invece di un ciclo complesso.
Secondo l'identitร di Pascal,
nCr = (n-1)Cr + (n-1)C(r-1)
Quindi, ci saranno 2 logiche ricorsive affinchรฉ l'algoritmo ricorsivo trovi una combinazione di r elementi da un dato array di dimensione n.
- L'elemento รจ incluso nella combinazione corrente
- L'elemento รจ escluso dalla combinazione corrente
Soprannome Code
function combination: pass in: inputArray, combinationArray, n, r, index, i if the index is equal to r: for each element in combination array: print each element if i>=n: return combinationArray[index] = inputArray[i] combination(inputArray, combinationArray, n, r, index+1, i+1) combination(inputArray, combinationArray, n, r, index, i+1)
Implementazione in C/C++
#include<bits/stdc++.h> #include<stdio.h> void Combination(char inputArray[], char combinationArray[], int n, int r, int index, int i) { if (index == r) { for (int j = 0; j < r; j++) { printf("%c", combinationArray[j]); } printf("\n"); return; } if (i >= n) return; combinationArray[index] = inputArray[i]; Combination(inputArray, combinationArray, n, r, index + 1, i + 1); Combination(inputArray, combinationArray, n, r, index, i + 1); } int main() { char inputArray[] = {'R','G','Y','B','I'}; int n = sizeof(inputArray) / sizeof(inputArray[0]); int r = 3; char combinationArray[r]; printf("Combinations:\n"); Combination(inputArray, combinationArray, n, r, 0, 0); }
Produzione:
Combinations: RGY RGB RGI RYB RYI RBI GYB GYI GBI YBI
implementazione in Python
def Combination(inputArray, combinationArray, n, r, index, i): if index == r: for item in combinationArray: print(item, end = " ") print() return if i >= n: return combinationArray[index] = inputArray[i] Combination(inputArray, combinationArray, n, r, index + 1, i + 1); Combination(inputArray, combinationArray, n, r, index, i + 1); inputArray = "RGYBI" n = len(inputArray) r = 3 combinationArray = [""] * r Combination(inputArray, combinationArray, n, r, 0, 0)
Produzione:
R G Y R G B R G I R Y B R Y I R B I G Y B G Y I G B I Y B I
Gestione delle combinazioni duplicate
A volte potrebbero esserci elementi duplicati nell'array di input.
Per esempio,
- L'array di input contiene n = {5, 2, 3, 1, 5}.
- Qui possiamo vedere che 5 รจ presente per 2 volte.
- Ora, se vogliamo eseguire il codice per questo array, verranno ripetute alcune combinazioni.
- Troveremo {5, 2, 5}, {5, 2, 3} ecc. oppure qualsiasi combinazione che contenga 5 verrร ripetuta.
Possiamo utilizzare questi due metodi:
- Ordina l'array di input. L'ordinamento richiederร tempo O(nlog(n)).
- Quindi aumenta il valore di i, mentre il valore i e il valore i+1 sono uguali. In pratica inserisci le seguenti due righe di codice nella funzione Combination.
// For c/c++ while(inputArray[i] == inputArray[i+1]){ i++; }
# for python while inputArray[i]==inputArray[i+1]: i+=1
Utilizzando un dizionario o una mappa non ordinata per track combinazioni duplicate
Quindi, se non vogliamo ordinare gli elementi per tracper duplicare il contenuto, possiamo seguire i passaggi indicati.
Passo 1) Dichiarare un dizionario globale o una hashmap.
Passo 2) Spingi la combinazione generata sull'hashmap e aumenta il valore di uno. La combinazione รจ la chiave e la loro occorrenza sono valori.
Passo 3) una volta terminata l'esecuzione della funzione, stamperemo semplicemente tutte le chiavi dall'hashmap o dal dizionario.
Ecco l'implementazione in Python
unique_combination = dict() def Combination(inputArray, combinationArray, n, r, index, i): if index == r: temp_combination = "" for item in combinationArray: temp_combination += item unique_combination[temp_combination] = unique_combination.get(temp_combination, 0) + 1 return if i >= n: return combinationArray[index] = inputArray[i] Combination(inputArray, combinationArray, n, r, index + 1, i + 1); Combination(inputArray, combinationArray, n, r, index, i + 1); inputArray = "RGYBIB" n = len(inputArray) r = 3 combinationArray = [""] * r Combination(inputArray, combinationArray, n, r, 0, 0) for item in unique_combination.keys(): print(item)
Produzione:
RGY RGB RGI RYB RYI RBI RBB RIB GYB GYI GBI GBB GIB YBI YBB YIB BIB
Qui puoi vedere che l'input era "RGYBIB". In generale, dovrebbero verificarsi alcune combinazioni duplicate. Ma poichรฉ abbiamo utilizzato un dizionario e abbiamo trattato ciascuna combinazione come chiave, possiamo stampare solo la combinazione univoca.
Ora, se scrivi "print(unique_combination)", puoi vedere la frequenza di ciascuna combinazione. Verrร visualizzato in questo modo:
{'RGY': 1, 'RGB': 2, 'RGI': 1, 'RYB': 2, 'RYI': 1, 'RBI': 1, 'RBB': 1, 'RIB': 1, 'GYB': 2, 'GYI': 1, 'GBI': 1, 'GBB': 1, 'GIB': 1, 'YBI': 1, 'YBB': 1, 'YIB': 1, 'BIB': 1}
Quindi, possiamo vedere che RGB, RYB, GYB si sono verificati 2 volte. La complessitร temporale dell'inserimento della chiave in un dizionario รจ fondamentalmente O(1). Quindi, se si utilizza un dizionario, la complessitร temporale totale per l'esecuzione del codice sarร :
O(1) + O(n*n)
Equivalente a O(n*n).
Utilizzando il metodo precedente per track duplicati, per l'ordinamento รจ necessario O(n*log(n)); per il confronto รจ necessario O(n), e la funzione stessa richiede O(n*n). La complessitร temporale totale sarร :
O(n*log(n)) + O(n) +O(n*n)


