Kombinační algoritmus: Vytiskněte všechny možné kombinace R
Co je to Kombinace?
Kombinace je druh uspořádání některých daných objektů. Z matematického hlediska je Kombinace množinou možností/výběru položek z jedinečné množiny položek/objektů. Zde na pořadí položek nezáleží. Je také známá jako metoda výpočtu celkového výsledku události, kde na pořadí výsledku nezáleží.
Například dostanete tašku s 5 různými barvami a požádáte o vytvoření vzoru s libovolnými 3 barvami. Můžete si také vybrat libovolné 3 barvy ze 4 a pak je uspořádat v různém pořadí.
Předpokládejme, že barvy jsou RGYBI (R= červená, G= zelená, Y= žlutá, B= modrá, I= indigová). Takže možný vzor může být RGB, RGY atd.
Podívejme se na následující obrázek:

Vysvětlení:
- Vezměte libovolné 4 barvy z 5 a uveďte je
- Z každého bloku 4 barev vyberte libovolné 3 a uveďte je všechny. Například jsme na obrázku vybrali pouze „RGBI“ a ukázali jsme 4 kombinace.
- Je za tím teorie, jak vypočítat celkový počet kombinací, které můžeme udělat. Kombinace r prvků z n může být matematicky prezentována jako:
Znamení "!" znamená faktoriální, Například,
N! = N* (N-1) * (N-2) * … * 3 * 2 * 1
Řekni, 5! = 5*4*3*2*1 = 120
Takže pro náš výše uvedený problém máme 5 barev, což znamená n = 5, a v každém daném okamžiku musíme vybrat libovolné 3. Takže r = 3. Po výpočtu dostaneme,
Pro výše uvedený scénář je možných celkem 10 barevných kombinací.
Analýza časové složitosti pro kombinaci
Nyní řekněme, že máme-li pole o velikosti n, jsme požádáni, abychom z pole vzali r prvků a provedli kombinace r prvků.
Pokud je zadáno pole o velikosti n, bude trvat O(n2) čas na provedení úkolu. Také, pokud chceme odstranit duplicitní záznam, pak
Musíme provést následující kroky:
Krok 1) Seřaďte data vstupního pole vzestupně. Časová složitost řazení je O(n*log(n)).
Krok 2) Vytvořte další pole obsahující jedinečný prvek z daných dat dočasného pole.
Krok 3) Poté proveďte kombinační funkci.
Celková časová složitost se tedy stává = Na2) + O(nLog(n)). Můžeme to považovat za O(n2), jako n2 je mnohem větší než n*log(n).
Metoda 1: Pevný prvek s rekurzí
V této metodě vybereme prvek a pak najdeme kombinaci prvků r-1. Když vybíráme prvek ze zbytku prvku, děláme to rekurzivně, a proto se tomu říká fixní prvek a rekurze.
Ukažme si algoritmus krok za krokem pomocí diagramu:
Kroky jsou uvedeny níže:
Krok 1) V první vrstvě vezměte n-r+1 prvků. To znamená, že jsme vzali 3 prvky.
Krok 2) Vyberte prvek z 2. vrstvy a vezměte jej až k č. Takže když vezmeme „R“, pak s R můžeme vzít G, Y a B.
Krok 3) Vyberte prvek ze 3. vrstvy a přeneste jej k n-tému prvku a vytvořte bloky obsahující každý 3 prvky.
Výše uvedený obrázek je návratová hodnota z rekurze. Vytiskne se pouze poslední vrstva.
Pseudo kód
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
Implementace v 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 & lt; r; i++) { printf("%c", combinationArray[i]); } printf("\n"); return; } for (int i = start; i & lt; = end & amp; & amp; end - i + 1 & gt; = 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); }
Výstup:
Combinations: RGY RGB RGI RYB RYI RBI GYB GYI GBI YBI
provádění 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 & lt; = end and end - i + 1 & gt; = 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)
Výstup:
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
Metoda 2 (zahrnout a vyloučit každý prvek)
Tato metoda je založena na Pascalově identitě. Dříve jsme pro výpočet nCr používali rekurzi. Zde je metoda pouze rozdělena namísto složité smyčky.
Podle Pascalovy identity
nCr = (n-1)Cr + (n-1)C(r-1)
Takže pro rekurzivní algoritmus budou existovat 2 rekurzivní logiky k nalezení kombinace r prvků z daného pole o velikosti n.
- Prvek je součástí aktuální kombinace
- Prvek je vyloučen z aktuální kombinace
Pseudo kód
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)
Implementace v 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 & lt; r; j++) { printf("%c", combinationArray[j]); } printf("\n"); return; } if (i & gt; = 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); }
Výstup:
Combinations: RGY RGB RGI RYB RYI RBI GYB GYI GBI YBI
provádění Python
def Combination(inputArray, combinationArray, n, r, index, i): if index == r: for item in combinationArray: print(item, end = " ") print() return if i & gt; = 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)
Výstup:
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
Zpracování duplicitních kombinací
Někdy mohou být ve vstupním poli duplicitní prvky.
Například,
- Vstupní pole obsahuje n = {5, 2, 3, 1, 5}.
- Zde vidíme, že 5 je přítomno 2krát.
- Nyní, pokud chceme spustit kód pro toto pole, některé kombinace se budou opakovat.
- Zjistíme, že {5, 2, 5}, {5, 2, 3} atd. nebo jakákoli kombinace obsahující 5 se bude opakovat.
Můžeme použít tyto dvě metody:
- Seřadit vstupní pole. Třídění bude trvat O(nlog(n)) čas.
- Potom zvyšte hodnotu i, zatímco hodnota i a i+1 je stejná. V podstatě vložte následující dva řádky kódu do funkce Kombinace.
// For c/c++ while(inputArray[i] == inputArray[i+1]){ i++; }
# for python while inputArray[i]==inputArray[i+1]: i+=1
Použití slovníku nebo neuspořádané mapy ke sledování duplicitních kombinací
Pokud tedy nechceme třídit prvky pro sledování duplikátu, můžeme postupovat podle uvedených kroků.
Krok 1) Deklarujte globální slovník nebo hashmap.
Krok 2) Posuňte vygenerovanou kombinaci do hashmapy a zvyšte hodnotu o jednu. Kombinace je klíč a jejich výskyt jsou hodnoty.
Krok 3) až funkce skončí, jednoduše vytiskneme všechny klíče z hashmapy nebo slovníku.
Zde je implementace v pythonu
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 & gt; = 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)
Výstup:
RGY RGB RGI RYB RYI RBI RBB RIB GYB GYI GBI GBB GIB YBI YBB YIB BIB
Zde můžete vidět, že vstup byl „RGYBIB“. Obecně by se měly vyskytovat některé duplicitní kombinace. Ale protože jsme použili slovník a považovali jsme každou kombinaci za klíč, můžeme vytisknout pouze jedinečnou kombinaci.
Nyní, když napíšete „print(unique_combination)“, uvidíte frekvenci každé kombinace. Ukáže se to takto:
{'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}
Můžeme tedy vidět, že RGB, RYB, GYB se vyskytly 2krát. Časová náročnost vložení klíče do slovníku je v zásadě O(1). Pokud tedy používáte slovník, celková časová složitost pro spuštění kódu bude:
O(1) + O(n*n)
Ekvivalent O(n*n).
Při použití předchozí metody ke sledování duplikátů potřebujeme O(n*log(n)) pro třídění; pro porovnání potřebujeme O(n) a samotná funkce má O(n*n). Celková časová náročnost bude:
O(n*log(n)) + O(n) +O(n*n)