Câu trả lời:
Có nhiều hướng khác nhau để làm điều đó. Các phương pháp phổ biến sử dụng đệ quy, ghi nhớ hoặc lập trình động. Ý tưởng cơ bản là bạn tạo ra một danh sách tất cả các chuỗi có độ dài 1, sau đó trong mỗi lần lặp, cho tất cả các chuỗi được tạo trong lần lặp cuối cùng, hãy thêm chuỗi đó được nối với từng ký tự trong chuỗi riêng lẻ. (chỉ số biến trong mã bên dưới theo dõi sự bắt đầu của lần lặp cuối cùng và lần lặp tiếp theo)
Một số mã giả:
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)
Sau đó, bạn cần xóa tất cả các chuỗi có độ dài nhỏ hơn x, chúng sẽ là mục nhập đầu tiên (x-1) * len (originalString) trong danh sách.
Tốt hơn hết là sử dụng quay lui
#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;
}
Bạn sẽ nhận được rất nhiều chuỗi, chắc chắn ...
Trong đó x và y là cách bạn xác định chúng và r là số lượng ký tự chúng tôi đang chọn từ - nếu tôi hiểu bạn chính xác. Bạn chắc chắn nên tạo ra những thứ này khi cần thiết và không bị cẩu thả và nói, tạo một bộ quyền hạn và sau đó lọc độ dài của chuỗi.
Sau đây chắc chắn không phải là cách tốt nhất để tạo ra những thứ này, nhưng đó là một điều thú vị, không hơn không kém.
Knuth (tập 4, fascicle 2, 7.2.1.3) cho chúng ta biết rằng tổ chức (s, t) tương đương với s + 1 thứ được thực hiện tại một thời điểm với sự lặp lại - một tổ chức (s, t) là ký hiệu được sử dụng bởi Knuth đó là bằng . Chúng ta có thể tìm ra điều này bằng cách trước tiên tạo ra từng tổ chức (s, t) ở dạng nhị phân (vì vậy, độ dài (s + t)) và đếm số 0 ở bên trái của mỗi 1.
10001000011101 -> trở thành hoán vị: {0, 3, 4, 4, 4, 1}
Giải pháp không đệ quy theo Knuth, ví dụ Python:
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"
chỉ với MỘT chuỗi được hiển thị (chính nó).
nextPermutation()
không trạng thái - chỉ mất đầu vào để hoán vị và các chỉ mục không được duy trì từ lần lặp đến lần lặp. Có thể làm như vậy bằng cách giả sử rằng đầu vào ban đầu đã được sắp xếp và tự tìm chỉ mục ( k0
và l0
), dựa trên nơi duy trì thứ tự. Sắp xếp một đầu vào như "54321" -> "12345" sẽ cho phép thuật toán này tìm thấy tất cả các hoán vị dự kiến. Nhưng vì nó thực hiện rất nhiều công việc bổ sung để tìm lại các chỉ mục đó cho mỗi hoán vị mà nó tạo ra, có nhiều cách hiệu quả hơn để thực hiện việc này không đệ quy.
Bạn có thể xem " Liệt kê hiệu quả các tập hợp con của tập hợp ", mô tả thuật toán để thực hiện một phần những gì bạn muốn - nhanh chóng tạo ra tất cả các tập hợp con của N ký tự từ độ dài x đến y. Nó chứa một triển khai trong C.
Đối với mỗi tập hợp con, bạn vẫn phải tạo tất cả các hoán vị. Chẳng hạn, nếu bạn muốn có 3 ký tự từ "abcde", thuật toán này sẽ cung cấp cho bạn "abc", "abd", "abe" ... nhưng bạn phải hoán vị từng ký tự để có được "acb", "bac", "Bca", v.v.
Một số mã Java hoạt động dựa trên câu trả lời của Sarp :
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);
}
}
Đây là một giải pháp đơn giản trong C #.
Nó chỉ tạo ra các hoán vị riêng biệt của một chuỗi nhất định.
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;
}
}
Có rất nhiều câu trả lời tốt ở đây. Tôi cũng đề xuất một giải pháp đệ quy rất đơn giản trong C ++.
#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;
});
}
Lưu ý : chuỗi có ký tự lặp lại sẽ không tạo ra hoán vị duy nhất.
Tôi vừa đánh nó nhanh lên trong Ruby:
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
Bạn có thể xem xét API ngôn ngữ để xây dựng các hàm loại hoán vị và bạn có thể viết mã được tối ưu hóa hơn, nhưng nếu các con số quá cao, tôi không chắc có nhiều cách để có nhiều kết quả .
Dù sao, ý tưởng đằng sau mã được bắt đầu bằng chuỗi có độ dài 0, sau đó theo dõi tất cả các chuỗi có độ dài Z trong đó Z là kích thước hiện tại trong lần lặp. Sau đó, đi qua từng chuỗi và nối từng ký tự vào từng chuỗi. Cuối cùng ở cuối, loại bỏ bất kỳ cái nào dưới ngưỡng x và trả về kết quả.
Tôi đã không kiểm tra nó với đầu vào vô nghĩa (danh sách ký tự null, giá trị lạ của x và y, v.v.).
Đây là bản dịch của phiên bản Ruby của Mike, sang Common Lisp:
(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)))))
Và một phiên bản khác, ngắn hơn một chút và sử dụng nhiều tính năng cơ sở vòng lặp hơn:
(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)))))
Đây là một từ đơn giản giải pháp đệ quy C #:
Phương pháp:
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;
}
Gọi điện thoại:
string[] letters = new string[]{"a","b","c"};
ArrayList words = CalculateWordPermutations(letters, new ArrayList(), 0);
... và đây là phiên bản C:
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;
}
hoán vị (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 * )] Để xóa trùng lặp khi chèn từng kiểm tra bảng chữ cái để xem chuỗi trước kết thúc với cùng một bảng chữ cái (tại sao? -xuất hiện)
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;
}
In tất cả các hoán vị sans trùng lặp
Giải pháp đệ quy trong C ++
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;
}
}
}
Trong Perl, nếu bạn muốn giới hạn bản thân trong bảng chữ cái chữ thường, bạn có thể làm điều này:
my @result = ("a" .. "zzzz");
Điều này cung cấp cho tất cả các chuỗi có thể có từ 1 đến 4 ký tự bằng cách sử dụng các ký tự chữ thường. Đối với chữ hoa, thay đổi "a"
thành "A"
và "zzzz"
sang "ZZZZ"
.
Đối với trường hợp hỗn hợp, việc này trở nên khó khăn hơn nhiều và có lẽ không thể thực hiện được với một trong những toán tử dựng sẵn của Perl như thế.
Ruby trả lời có tác dụng:
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;
}
}
Đệ quy Java sau đây in tất cả các hoán vị của một chuỗi đã cho:
//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);
}
}
Sau đây là phiên bản cập nhật của phương pháp "permut" ở trên, làm cho n! (n factorial) các cuộc gọi đệ quy ít hơn so với phương thức trên
//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()));
}
}
Tôi không chắc tại sao bạn lại muốn làm điều này ngay từ đầu. Tập kết quả cho bất kỳ giá trị lớn vừa phải của x và y sẽ rất lớn và sẽ tăng theo cấp số nhân khi x và / hoặc y lớn hơn.
Giả sử tập hợp các ký tự có thể của bạn là 26 chữ cái viết thường của bảng chữ cái và bạn yêu cầu ứng dụng của mình tạo ra tất cả các hoán vị trong đó length = 5. Giả sử bạn không hết bộ nhớ, bạn sẽ nhận được 11.881.376 (tức là 26 cho sức mạnh của 5) chuỗi trở lại. Bump có độ dài lên đến 6 và bạn sẽ nhận lại 308.915.776 chuỗi. Những con số này nhận được rất lớn, rất nhanh chóng.
Đây là một giải pháp tôi đưa vào Java. Bạn sẽ cần cung cấp hai đối số thời gian chạy (tương ứng với x và y). Chúc vui vẻ.
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);
}
}
}
}
Đây là phiên bản không đệ quy mà tôi đã nghĩ ra, trong javascript. Nó không dựa trên cơ sở không đệ quy của Knuth ở trên, mặc dù nó có một số điểm tương đồng trong việc hoán đổi thành phần. Tôi đã xác minh tính chính xác của nó cho các mảng đầu vào lên tới 8 phần tử.
Một tối ưu hóa nhanh chóng sẽ được bay trước out
mảng và tránh push()
.
Ý tưởng cơ bản là:
Đưa ra một mảng nguồn duy nhất, tạo ra một mảng các mảng mới đầu tiên lần lượt hoán đổi phần tử đầu tiên với từng phần tử tiếp theo, mỗi lần để các phần tử khác không bị xáo trộn. ví dụ: đã cho 1234, tạo 1234, 2134, 3214, 4231.
Sử dụng từng mảng từ đường chuyền trước làm hạt giống cho đường chuyền mới, nhưng thay vì hoán đổi phần tử đầu tiên, hãy hoán đổi phần tử thứ hai với mỗi phần tử tiếp theo. Ngoài ra, lần này, không bao gồm mảng ban đầu trong đầu ra.
Lặp lại bước 2 cho đến khi hoàn thành.
Đây là mẫu mã:
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;
}
Trong hồng ngọc:
str = "a"
100_000_000.times {puts str.next!}
Nó khá nhanh, nhưng sẽ mất một chút thời gian =). Tất nhiên, bạn có thể bắt đầu tại "aaaaaaaa" nếu các chuỗi ngắn không thú vị với bạn.
Tôi có thể đã giải thích sai câu hỏi thực tế - trong một trong những bài đăng có vẻ như bạn chỉ cần một thư viện chuỗi bruteforce, nhưng trong câu hỏi chính có vẻ như bạn cần phải hoán vị một chuỗi cụ thể.
Vấn đề của bạn có phần giống với vấn đề này: http://beust.com/weblog/archives/000491.html (liệt kê tất cả các số nguyên trong đó không có chữ số nào lặp lại, dẫn đến rất nhiều ngôn ngữ giải quyết nó, với anh chàng ocaml sử dụng hoán vị và một số anh chàng java sử dụng một giải pháp khác).
Tôi cần điều này ngày hôm nay, và mặc dù các câu trả lời đã đưa tôi đi đúng hướng, nhưng chúng không hoàn toàn như những gì tôi muốn.
Đây là một triển khai bằng phương pháp của Heap. Độ dài của mảng phải ít nhất là 3 và để xem xét thực tế không lớn hơn 10 hoặc hơn, tùy thuộc vào những gì bạn muốn làm, sự kiên nhẫn và tốc độ đồng hồ.
Trước khi bạn vào vòng lặp của mình, hãy khởi tạo Perm(1 To N)
với hoán vị đầu tiên, Stack(3 To N)
với số 0 * và Level
với 2
**. Khi kết thúc cuộc gọi vòng lặp NextPerm
, sẽ trả về false khi chúng ta hoàn thành.
* VB sẽ làm điều đó cho bạn.
** Bạn có thể thay đổi NextPerm một chút để làm cho điều này không cần thiết, nhưng nó rõ ràng hơn như thế này.
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
Các phương pháp khác được mô tả bởi các tác giả khác nhau. Knuth mô tả hai, một cho thứ tự từ vựng, nhưng phức tạp và chậm, cái còn lại được gọi là phương pháp thay đổi đơn giản. Jie Gao và Dianjun Wang cũng đã viết một bài báo thú vị.
Mã này trong python, khi được gọi với allowed_characters
set [0,1]
và max 4 ký tự, sẽ tạo ra 2 ^ 4 kết quả:
['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()
Hy vọng điều này là sử dụng cho bạn. Hoạt động với bất kỳ ký tự nào, không chỉ số
Đây là một liên kết mô tả cách in hoán vị của một chuỗi. http://nipun-linuxtips.blogspot.in/2012/11/print-all-permutations-of-char character-in.html
Mặc dù điều này không trả lời chính xác câu hỏi của bạn, đây là một cách để tạo ra mọi hoán vị của các chữ cái từ một số chuỗi có cùng độ dài: ví dụ: nếu các từ của bạn là "coffee", "j Joomla" và "moodle", bạn có thể mong đợi đầu ra như "coodle", "joodee", "joffle", v.v.
Về cơ bản, số lượng kết hợp là (số lượng từ) cho sức mạnh của (số lượng chữ cái trên mỗi từ). Vì vậy, chọn một số ngẫu nhiên trong khoảng từ 0 đến số kết hợp - 1, chuyển đổi số đó thành cơ sở (số từ), sau đó sử dụng mỗi chữ số của số đó làm chỉ báo cho từ nào sẽ lấy chữ cái tiếp theo.
ví dụ: trong ví dụ trên. 3 từ, 6 chữ cái = 729 kết hợp. Chọn một số ngẫu nhiên: 465. Chuyển đổi sang cơ sở 3: 122020. Lấy chữ cái đầu tiên từ từ 1, 2 từ từ 2, 3 từ từ 2, 4 từ từ 0 ... và bạn nhận được ... "joofle".
Nếu bạn muốn tất cả các hoán vị, chỉ cần lặp từ 0 đến 728. Tất nhiên, nếu bạn chỉ chọn một giá trị ngẫu nhiên, một cách đơn giản hơn ít gây nhầm lẫn sẽ là lặp qua các chữ cái. Phương pháp này cho phép bạn tránh đệ quy, nếu bạn muốn tất cả các hoán vị, cộng với nó làm cho bạn trông giống như bạn biết Toán học (tm) !
Nếu số lượng kết hợp quá nhiều, bạn có thể chia nó thành một chuỗi các từ nhỏ hơn và ghép chúng ở cuối.
c # lặp đi lặp lại:
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
Đây là nhận của tôi về một phiên bản không đệ quy
Các giải pháp pythonic:
from itertools import permutations
s = 'ABCDEF'
p = [''.join(x) for x in permutations(s)]
Vâng đây là một giải pháp O (n!) Thanh lịch, không đệ quy:
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;
}