Değişken bir karakter listesi içeren, x ve y karakterleri arasındaki bir dizenin olası tüm permütasyonlarının bir listesini nasıl oluşturabilirim.
Herhangi bir dil işe yarayacaktır, ancak taşınabilir olmalıdır.
Değişken bir karakter listesi içeren, x ve y karakterleri arasındaki bir dizenin olası tüm permütasyonlarının bir listesini nasıl oluşturabilirim.
Herhangi bir dil işe yarayacaktır, ancak taşınabilir olmalıdır.
Yanıtlar:
Bunu yapmanın birkaç yolu vardır. Yaygın yöntemlerde özyineleme, not veya dinamik programlama kullanılır. Temel fikir, uzunluk 1'in tüm dizelerinin bir listesini üretmeniz, daha sonra her yinelemede, son yinelemede üretilen tüm dizeler için, dizedeki her karakterle birleştirilen dizeyi ayrı ayrı eklemenizdir. (aşağıdaki koddaki değişken dizin son ve sonraki yinelemenin başlangıcını takip eder)
Bazı sözde kod:
list = originalString.split('')
index = (0,0)
list = [""]
for iteration n in 1 to y:
index = (index[1], len(list))
for string s in list.subset(index[0] to end):
for character c in originalString:
list.add(s + c)
daha sonra, x'den küçük tüm dizeleri kaldırmanız gerekir; bunlar listedeki ilk (x-1) * len (originalString) girişler olur.
Geri izlemeyi kullanmak daha iyidir
#include <stdio.h>
#include <string.h>
void swap(char *a, char *b) {
char temp;
temp = *a;
*a = *b;
*b = temp;
}
void print(char *a, int i, int n) {
int j;
if(i == n) {
printf("%s\n", a);
} else {
for(j = i; j <= n; j++) {
swap(a + i, a + j);
print(a, i + 1, n);
swap(a + i, a + j);
}
}
}
int main(void) {
char a[100];
gets(a);
print(a, 0, strlen(a) - 1);
return 0;
}
Bir sürü ip alacaksın, bu kesin ...
Burada x ve y bunları nasıl tanımladığınız ve r, seçtiğimiz karakter sayısıdır - eğer sizi doğru anlıyorsam. Bunları kesinlikle gerektiği gibi üretmeli ve özensizleşmemeli ve bir güç kümesi oluşturmalı ve sonra dizelerin uzunluğunu filtrelemelisiniz.
Aşağıdakiler kesinlikle bunları üretmenin en iyi yolu değil, ama ilginç bir kenara, hiç de az değil.
Knuth (cilt 4, fascicle 2, 7.2.1.3) bize, (s, t)-kombinasyonunun tekrar ile bir defada alınan s + 1 şeye eşdeğer olduğunu söyler - bir (s, t)-kombinasyonunun kullandığı gösterim Eşittir . İlk önce her bir (s, t) kombinasyonunu ikili biçimde (yani, uzunluk (s + t)) oluşturarak ve her 1'in solundaki 0 sayısını sayarak çözebiliriz.
10001000011101 -> permütasyon olur: {0, 3, 4, 4, 4, 1}
Knuth, Python örneğine göre özyinelemesiz çözüm:
def nextPermutation(perm):
k0 = None
for i in range(len(perm)-1):
if perm[i]<perm[i+1]:
k0=i
if k0 == None:
return None
l0 = k0+1
for i in range(k0+1, len(perm)):
if perm[k0] < perm[i]:
l0 = i
perm[k0], perm[l0] = perm[l0], perm[k0]
perm[k0+1:] = reversed(perm[k0+1:])
return perm
perm=list("12345")
while perm:
print perm
perm = nextPermutation(perm)
"54321"
sadece TEK dize (kendisi) gösterdi.
nextPermutation()
, vatansızdır - sadece permütasyon için girişi alır ve endeksler yinelemeden yinelemeye kadar korunmaz. İlk girişin sıralandığını varsayarak ve siparişin nerede korunduğuna bağlı olarak indeksleri ( k0
ve l0
) bularak yapabilir . "54321" -> "12345" gibi bir girdiyi sıralamak, bu algoritmanın beklenen tüm permütasyonları bulmasına izin verecektir. Ancak, oluşturduğu her permütasyon için bu indeksleri yeniden bulmak için fazladan ekstra iş yaptığı için, bunu tekrarlamalı olarak yapmanın daha etkili yolları vardır.
İstediğiniz şeyin bir parçasını yapmak için bir algoritma tanımlayan " Bir Kümenin Alt Kümelerini Etkin Bir Şekilde Numaralandırma" konusuna bakabilirsiniz - x uzunluğundan y'ye kadar tüm N karakter alt kümelerini hızlı bir şekilde oluşturun. C'de bir uygulama içerir.
Her alt küme için yine de tüm permütasyonları oluşturmanız gerekir. Örneğin, "abcde" den 3 karakter istiyorsanız, bu algoritma size "abc", "abd", "abe" verir, ancak her birinin "acb", "bac" almasına izin vermeniz gerekir, "bca" vb.
Sarp'ın cevabına dayanan bazı çalışan Java kodları :
public class permute {
static void permute(int level, String permuted,
boolean used[], String original) {
int length = original.length();
if (level == length) {
System.out.println(permuted);
} else {
for (int i = 0; i < length; i++) {
if (!used[i]) {
used[i] = true;
permute(level + 1, permuted + original.charAt(i),
used, original);
used[i] = false;
}
}
}
}
public static void main(String[] args) {
String s = "hello";
boolean used[] = {false, false, false, false, false};
permute(0, "", used, s);
}
}
İşte C # 'da basit bir çözüm.
Belirli bir dizenin yalnızca belirgin permütasyonlarını üretir.
static public IEnumerable<string> permute(string word)
{
if (word.Length > 1)
{
char character = word[0];
foreach (string subPermute in permute(word.Substring(1)))
{
for (int index = 0; index <= subPermute.Length; index++)
{
string pre = subPermute.Substring(0, index);
string post = subPermute.Substring(index);
if (post.Contains(character))
continue;
yield return pre + character + post;
}
}
}
else
{
yield return word;
}
}
Burada çok iyi cevaplar var. Ayrıca C ++ 'da çok basit bir özyinelemeli çözüm öneririm.
#include <string>
#include <iostream>
template<typename Consume>
void permutations(std::string s, Consume consume, std::size_t start = 0) {
if (start == s.length()) consume(s);
for (std::size_t i = start; i < s.length(); i++) {
std::swap(s[start], s[i]);
permutations(s, consume, start + 1);
}
}
int main(void) {
std::string s = "abcd";
permutations(s, [](std::string s) {
std::cout << s << std::endl;
});
}
Not : tekrarlanan karakterlere sahip dizeler benzersiz permütasyonlar üretmez.
Ruby'de bunu çabucak çırptım:
def perms(x, y, possible_characters)
all = [""]
current_array = all.clone
1.upto(y) { |iteration|
next_array = []
current_array.each { |string|
possible_characters.each { |c|
value = string + c
next_array.insert next_array.length, value
all.insert all.length, value
}
}
current_array = next_array
}
all.delete_if { |string| string.length < x }
end
Dahili permütasyon tipi fonksiyonlar için dil API'sine bakabilirsiniz ve daha optimize edilmiş kod yazabilirsiniz, ancak sayılar bu kadar yüksekse, çok fazla sonuç almanın bir yolu olduğundan emin değilim .
Her neyse, kodun arkasındaki fikir 0 uzunluk dizesiyle başlar, sonra Z uzunluğunun tüm dizelerini takip edin, burada Z yinelemedeki geçerli boyuttur. Ardından, her dizeyi gözden geçirin ve her karakteri her dizeye ekleyin. Sonunda, x eşiğinin altında olanları kaldırın ve sonucu döndürün.
Potansiyel olarak anlamsız girdi (null karakter listesi, garip x ve y değerleri, vb.) İle test etmedim.
Mike'ın Ruby versiyonunun Common Lisp'e çevirisi:
(defun perms (x y original-string)
(loop with all = (list "")
with current-array = (list "")
for iteration from 1 to y
do (loop with next-array = nil
for string in current-array
do (loop for c across original-string
for value = (concatenate 'string string (string c))
do (push value next-array)
(push value all))
(setf current-array (reverse next-array)))
finally (return (nreverse (delete-if #'(lambda (el) (< (length el) x)) all)))))
Ve biraz daha kısa ve daha fazla döngü tesisi özellikleri kullanan başka bir sürüm:
(defun perms (x y original-string)
(loop repeat y
collect (loop for string in (or (car (last sets)) (list ""))
append (loop for c across original-string
collect (concatenate 'string string (string c)))) into sets
finally (return (loop for set in sets
append (loop for el in set when (>= (length el) x) collect el)))))
İşte basit bir kelime C # özyinelemeli çözüm:
Yöntem:
public ArrayList CalculateWordPermutations(string[] letters, ArrayList words, int index)
{
bool finished = true;
ArrayList newWords = new ArrayList();
if (words.Count == 0)
{
foreach (string letter in letters)
{
words.Add(letter);
}
}
for(int j=index; j<words.Count; j++)
{
string word = (string)words[j];
for(int i =0; i<letters.Length; i++)
{
if(!word.Contains(letters[i]))
{
finished = false;
string newWord = (string)word.Clone();
newWord += letters[i];
newWords.Add(newWord);
}
}
}
foreach (string newWord in newWords)
{
words.Add(newWord);
}
if(finished == false)
{
CalculateWordPermutations(letters, words, words.Count - newWords.Count);
}
return words;
}
Arayan:
string[] letters = new string[]{"a","b","c"};
ArrayList words = CalculateWordPermutations(letters, new ArrayList(), 0);
... ve işte C versiyonu:
void permute(const char *s, char *out, int *used, int len, int lev)
{
if (len == lev) {
out[lev] = '\0';
puts(out);
return;
}
int i;
for (i = 0; i < len; ++i) {
if (! used[i])
continue;
used[i] = 1;
out[lev] = s[i];
permute(s, out, used, len, lev + 1);
used[i] = 0;
}
return;
}
permütasyon (ABC) -> A.perm (BC) -> A.perm [B.perm (C)] -> A.perm [( * B C), (C B * )] -> [( * A BC ), (B A C), (BC A * ), ( * A CB), (C A B), (CB A * )] Her alfabe eklerken yinelenenleri kaldırmak için önceki dizenin aynı alfabe ile bitip bitmediğini kontrol edin (neden? - egzersiz)
public static void main(String[] args) {
for (String str : permStr("ABBB")){
System.out.println(str);
}
}
static Vector<String> permStr(String str){
if (str.length() == 1){
Vector<String> ret = new Vector<String>();
ret.add(str);
return ret;
}
char start = str.charAt(0);
Vector<String> endStrs = permStr(str.substring(1));
Vector<String> newEndStrs = new Vector<String>();
for (String endStr : endStrs){
for (int j = 0; j <= endStr.length(); j++){
if (endStr.substring(0, j).endsWith(String.valueOf(start)))
break;
newEndStrs.add(endStr.substring(0, j) + String.valueOf(start) + endStr.substring(j));
}
}
return newEndStrs;
}
Tüm permütasyonları ve kopyaları yazdırır
C ++ 'da özyinelemeli çözüm
int main (int argc, char * const argv[]) {
string s = "sarp";
bool used [4];
permute(0, "", used, s);
}
void permute(int level, string permuted, bool used [], string &original) {
int length = original.length();
if(level == length) { // permutation complete, display
cout << permuted << endl;
} else {
for(int i=0; i<length; i++) { // try to add an unused character
if(!used[i]) {
used[i] = true;
permute(level+1, original[i] + permuted, used, original); // find the permutations starting with this string
used[i] = false;
}
}
}
Perl'de, kendinizi küçük harfli alfabe ile sınırlamak istiyorsanız, bunu yapabilirsiniz:
my @result = ("a" .. "zzzz");
Bu, küçük harfler kullanarak 1 ile 4 karakter arasındaki tüm olası dizeleri verir. Büyük harf "a"
için "A"
ve "zzzz"
olarak değiştirin "ZZZZ"
.
Karışık durumda, çok daha zorlaşır ve muhtemelen Perl'in böyle yerleşik operatörlerinden biriyle yapılamaz.
Yakut işe yarayan cevap:
class String
def each_char_with_index
0.upto(size - 1) do |index|
yield(self[index..index], index)
end
end
def remove_char_at(index)
return self[1..-1] if index == 0
self[0..(index-1)] + self[(index+1)..-1]
end
end
def permute(str, prefix = '')
if str.size == 0
puts prefix
return
end
str.each_char_with_index do |char, index|
permute(str.remove_char_at(index), prefix + char)
end
end
# example
# permute("abc")
import java.util.*;
public class all_subsets {
public static void main(String[] args) {
String a = "abcd";
for(String s: all_perm(a)) {
System.out.println(s);
}
}
public static Set<String> concat(String c, Set<String> lst) {
HashSet<String> ret_set = new HashSet<String>();
for(String s: lst) {
ret_set.add(c+s);
}
return ret_set;
}
public static HashSet<String> all_perm(String a) {
HashSet<String> set = new HashSet<String>();
if(a.length() == 1) {
set.add(a);
} else {
for(int i=0; i<a.length(); i++) {
set.addAll(concat(a.charAt(i)+"", all_perm(a.substring(0, i)+a.substring(i+1, a.length()))));
}
}
return set;
}
}
Aşağıdaki Java özyinelemesi, belirli bir dizenin tüm permütasyonlarını yazdırır:
//call it as permut("",str);
public void permut(String str1,String str2){
if(str2.length() != 0){
char ch = str2.charAt(0);
for(int i = 0; i <= str1.length();i++)
permut(str1.substring(0,i) + ch + str1.substring(i,str1.length()),
str2.substring(1,str2.length()));
}else{
System.out.println(str1);
}
}
Aşağıda n yapar "permut" yönteminin güncellenmiş sürümü aşağıdadır! (n faktöryel) yukarıdaki yönteme kıyasla daha az özyinelemeli çağrı
//call it as permut("",str);
public void permut(String str1,String str2){
if(str2.length() > 1){
char ch = str2.charAt(0);
for(int i = 0; i <= str1.length();i++)
permut(str1.substring(0,i) + ch + str1.substring(i,str1.length()),
str2.substring(1,str2.length()));
}else{
char ch = str2.charAt(0);
for(int i = 0; i <= str1.length();i++)
System.out.println(str1.substring(0,i) + ch + str1.substring(i,str1.length()),
str2.substring(1,str2.length()));
}
}
Bunu ilk etapta neden yapmak isteyeceğinizden emin değilim. Orta derecede büyük x ve y değerleri için sonuç kümesi büyük olacaktır ve x ve / veya y büyüdükçe katlanarak büyüyecektir.
Diyelim ki, olası karakter kümeniz alfabenin 26 küçük harfidir ve uygulamanızdan uzunluk = 5 olan tüm permütasyonları üretmesini istersiniz. 5) dizeleri geri. Bu uzunluğu 6'ya kadar çarptığınızda 308.915.776 dizeyi geri alırsınız. Bu sayılar çok çabuk acıyla büyüyor.
İşte Java'da bir araya getirdiğim bir çözüm. İki çalışma zamanı argümanı sağlamanız gerekir (x ve y'ye karşılık gelir). İyi eğlenceler.
public class GeneratePermutations {
public static void main(String[] args) {
int lower = Integer.parseInt(args[0]);
int upper = Integer.parseInt(args[1]);
if (upper < lower || upper == 0 || lower == 0) {
System.exit(0);
}
for (int length = lower; length <= upper; length++) {
generate(length, "");
}
}
private static void generate(int length, String partial) {
if (length <= 0) {
System.out.println(partial);
} else {
for (char c = 'a'; c <= 'z'; c++) {
generate(length - 1, partial + c);
}
}
}
}
Javascript'te bulduğum özyinelemeli olmayan bir sürüm. Eleman değişiminde bazı benzerliklere sahip olmasına rağmen, Knuth'un yukarıdaki özyinelemesiz olanı temel almaz. 8 öğeye kadar giriş dizileri için doğruluğunu doğruladım.
Hızlı bir optimizasyon out
diziyi önceden uçurur ve bundan kaçınır push()
.
Temel fikir:
Tek bir kaynak dizisi verildiğinde, ilk öğeyi sırayla her bir öğeyle sırayla değiştiren, her seferinde diğer öğeleri bozulmadan bırakarak yeni bir dizi dizi oluşturun. örneğin: 1234 verildi, 1234, 2134, 3214, 4231 oluşturun.
Önceki geçişteki her diziyi yeni geçiş için tohum olarak kullanın, ancak ilk öğeyi değiştirmek yerine ikinci öğeyi sonraki her öğeyle değiştirin. Ayrıca, bu sefer, orijinal diziyi çıktıya dahil etmeyin.
Tamamlanana kadar 2. adımı tekrarlayın.
İşte kod örneği:
function oxe_perm(src, depth, index)
{
var perm = src.slice(); // duplicates src.
perm = perm.split("");
perm[depth] = src[index];
perm[index] = src[depth];
perm = perm.join("");
return perm;
}
function oxe_permutations(src)
{
out = new Array();
out.push(src);
for (depth = 0; depth < src.length; depth++) {
var numInPreviousPass = out.length;
for (var m = 0; m < numInPreviousPass; ++m) {
for (var n = depth + 1; n < src.length; ++n) {
out.push(oxe_perm(out[m], depth, n));
}
}
}
return out;
}
Yakutta:
str = "a"
100_000_000.times {puts str.next!}
Oldukça hızlı, ama biraz zaman alacak =). Tabii ki, kısa dizeler sizin için ilginç değilse "aaaaaaaa" başlayabilirsiniz.
Gerçi gerçek soruyu yanlış yorumlamış olabilirim - mesajlardan birinde dizelerin bir bruteforce kütüphanesine ihtiyaç duyuyorsunuz gibi geldi, ancak ana soruda belirli bir dizeye izin vermeniz gerekiyor gibi geliyor.
Sorununuz buna benzer: http://beust.com/weblog/archives/000491.html (basamakların hiçbirinin tekrar etmediği tüm tamsayıları listeleyin, bu da bir çok dili çözdü. ocaml guy permutations ve bazı java guy başka bir çözüm kullanarak).
Bugün buna ihtiyacım vardı ve verilen cevaplar beni doğru yönde göstermesine rağmen, istediğim gibi değildi.
İşte Heap yöntemini kullanan bir uygulama. Dizinin uzunluğu en az 3 olmalıdır ve pratik hususlar için ne yapmak istediğinize, sabrınıza ve saat hızına bağlı olarak 10'dan büyük olmamalıdır.
Eğer döngü, initialise girmeden önce Perm(1 To N)
, ilk permütasyon ile Stack(3 To N)
sıfır ve * ile Level
birlikte 2
**. Döngü çağrısının sonunda, NextPerm
işimiz bittiğinde false döndürür.
* VB bunu sizin için yapacak.
** Bunu gereksiz kılmak için NextPerm'i biraz değiştirebilirsiniz, ancak bu daha açıktır.
Option Explicit
Function NextPerm(Perm() As Long, Stack() As Long, Level As Long) As Boolean
Dim N As Long
If Level = 2 Then
Swap Perm(1), Perm(2)
Level = 3
Else
While Stack(Level) = Level - 1
Stack(Level) = 0
If Level = UBound(Stack) Then Exit Function
Level = Level + 1
Wend
Stack(Level) = Stack(Level) + 1
If Level And 1 Then N = 1 Else N = Stack(Level)
Swap Perm(N), Perm(Level)
Level = 2
End If
NextPerm = True
End Function
Sub Swap(A As Long, B As Long)
A = A Xor B
B = A Xor B
A = A Xor B
End Sub
'This is just for testing.
Private Sub Form_Paint()
Const Max = 8
Dim A(1 To Max) As Long, I As Long
Dim S(3 To Max) As Long, J As Long
Dim Test As New Collection, T As String
For I = 1 To UBound(A)
A(I) = I
Next
Cls
ScaleLeft = 0
J = 2
Do
If CurrentY + TextHeight("0") > ScaleHeight Then
ScaleLeft = ScaleLeft - TextWidth(" 0 ") * (UBound(A) + 1)
CurrentY = 0
CurrentX = 0
End If
T = vbNullString
For I = 1 To UBound(A)
Print A(I);
T = T & Hex(A(I))
Next
Print
Test.Add Null, T
Loop While NextPerm(A, S, J)
J = 1
For I = 2 To UBound(A)
J = J * I
Next
If J <> Test.Count Then Stop
End Sub
Diğer yöntemler çeşitli yazarlar tarafından tarif edilmiştir. Knuth iki tanesini tanımlar, biri sözcüksel düzen verir, ancak karmaşık ve yavaştır, diğeri ise basit değişikliklerin yöntemi olarak bilinir. Jie Gao ve Dianjun Wang da ilginç bir makale yazdı.
Python'daki bu kod, allowed_characters
set [0,1]
ve max maksimum 4 karakterle çağrıldığında 2 ^ 4 sonuç oluşturur:
['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111']
def generate_permutations(chars = 4) :
#modify if in need!
allowed_chars = [
'0',
'1',
]
status = []
for tmp in range(chars) :
status.append(0)
last_char = len(allowed_chars)
rows = []
for x in xrange(last_char ** chars) :
rows.append("")
for y in range(chars - 1 , -1, -1) :
key = status[y]
rows[x] = allowed_chars[key] + rows[x]
for pos in range(chars - 1, -1, -1) :
if(status[pos] == last_char - 1) :
status[pos] = 0
else :
status[pos] += 1
break;
return rows
import sys
print generate_permutations()
Umarım bu sizin için yararlıdır. Sadece sayılarla değil, herhangi bir karakterle çalışır
Bir dizenin permütasyonlarının nasıl yazdırılacağını açıklayan bir bağlantı. http://nipun-linuxtips.blogspot.in/2012/11/print-all-permutations-of-characters-in.html
Bu, sorunuzu tam olarak cevaplamasa da, aynı uzunlukta birkaç dizeden harflerin her permütasyonunu oluşturmanın bir yolu: örneğin, kelimeleriniz "kahve", "joomla" ve "moodle" ise, "coodle", "joodee", "joffle" vb.
Temel olarak, kombinasyon sayısı gücünün (kelime sayısı) (kelime başına harf sayısı). Bu nedenle, 0 ile kombinasyon sayısı arasında rasgele bir sayı seçin - 1, bu sayıyı tabana (kelime sayısı) dönüştürün, ardından bu sayının her bir basamağını, bir sonraki harfi hangi kelimenin alacağı göstergesi olarak kullanın.
örneğin: yukarıdaki örnekte. 3 kelime, 6 harf = 729 kombinasyon. Rastgele bir sayı seçin: 465. Taban 3'e dönüştürün: 122020. İlk harfi 1, 2, 2, 3, 2, 4., 0 kelimesinden alın ... "joofle" olsun.
Tüm permütasyonları istiyorsanız, sadece 0'dan 728'e kadar döngü yapın. Tabii ki, sadece bir rastgele değer seçerseniz , harflerin üzerinde dolaşmak daha basit ve daha az kafa karıştırıcı bir yol olacaktır. Bu yöntem, tüm permütasyonları istiyorsanız, özyinelemeyi önlemenizi sağlar, ayrıca Math'ları (tm) bildiğiniz gibi görünmenizi sağlar !
Kombinasyon sayısı aşırı ise, bunu bir dizi küçük kelimeye ayırabilir ve sonunda birleştirebilirsiniz.
c # yinelemeli:
public List<string> Permutations(char[] chars)
{
List<string> words = new List<string>();
words.Add(chars[0].ToString());
for (int i = 1; i < chars.Length; ++i)
{
int currLen = words.Count;
for (int j = 0; j < currLen; ++j)
{
var w = words[j];
for (int k = 0; k <= w.Length; ++k)
{
var nstr = w.Insert(k, chars[i].ToString());
if (k == 0)
words[j] = nstr;
else
words.Add(nstr);
}
}
}
return words;
}
def gen( x,y,list): #to generate all strings inserting y at different positions
list = []
list.append( y+x )
for i in range( len(x) ):
list.append( func(x,0,i) + y + func(x,i+1,len(x)-1) )
return list
def func( x,i,j ): #returns x[i..j]
z = ''
for i in range(i,j+1):
z = z+x[i]
return z
def perm( x , length , list ): #perm function
if length == 1 : # base case
list.append( x[len(x)-1] )
return list
else:
lists = perm( x , length-1 ,list )
lists_temp = lists #temporarily storing the list
lists = []
for i in range( len(lists_temp) ) :
list_temp = gen(lists_temp[i],x[length-2],lists)
lists += list_temp
return lists
def permutation(str)
posibilities = []
str.split('').each do |char|
if posibilities.size == 0
posibilities[0] = char.downcase
posibilities[1] = char.upcase
else
posibilities_count = posibilities.length
posibilities = posibilities + posibilities
posibilities_count.times do |i|
posibilities[i] += char.downcase
posibilities[i+posibilities_count] += char.upcase
end
end
end
posibilities
end
İşte özyinelemeyen bir sürümü almam
Pitonik çözüm:
from itertools import permutations
s = 'ABCDEF'
p = [''.join(x) for x in permutations(s)]
İşte zarif, özyinelemesiz, O (n!) Bir çözüm:
public static StringBuilder[] permutations(String s) {
if (s.length() == 0)
return null;
int length = fact(s.length());
StringBuilder[] sb = new StringBuilder[length];
for (int i = 0; i < length; i++) {
sb[i] = new StringBuilder();
}
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
int times = length / (i + 1);
for (int j = 0; j < times; j++) {
for (int k = 0; k < length / times; k++) {
sb[j * length / times + k].insert(k, ch);
}
}
}
return sb;
}