2012-02-09 2 views
20

Поиск всех перестановок строки осуществляется с помощью известного алгоритма Steinhaus-Johnson-Trotter. Но если строка содержит повторяющиеся символы, такие как
AABB,
то возможные уникальные комбинации будет 4!/(2! * 2!) = 6Поиск всех уникальных перестановок строки без генерации дубликатов

Одним из способов достижения этого является то, что мы можем хранить его в массиве или так, а затем удалите дубликаты.

Есть ли более простой способ изменить алгоритм Джонсона, чтобы мы никогда не генерировали дублированные перестановки. (Наиболее эффективным способом)

+0

Какое определение перестановки? Является ли BA допустимой перестановкой AABB? – ElKamina

+2

no BA не является допустимой перестановкой AABB. – titan

+0

Пермутация - это одна последовательность перетасовки символов в строке. Для строки длины n и уникальных символов мы имеем общее число n! возможные уникальные перестановки – titan

ответ

1

В моем решении я генерирую рекурсивные параметры, каждый раз добавляя каждую букву, которую я не использовал столько раз, сколько мне нужно.

#include <string.h> 

void fill(char ***adr,int *pos,char *pref) { 
    int i,z=1; 
    //loop on the chars, and check if should use them 
    for (i=0;i<256;i++) 
     if (pos[i]) { 
      int l=strlen(pref); 
      //add the char 
      pref[l]=i; 
      pos[i]--; 
      //call the recursion 
      fill(adr,pos,pref); 
      //delete the char 
      pref[l]=0; 
      pos[i]++; 
      z=0; 
     } 
    if (z) strcpy(*(*adr)++,pref); 
} 

void calc(char **arr,const char *str) { 
    int p[256]={0}; 
    int l=strlen(str); 
    char temp[l+1]; 
    for (;l>=0;l--) temp[l]=0; 
    while (*str) p[*str++]++; 
    fill(&arr,p,temp); 
} 

использование пример:

#include <stdio.h> 
#include <string.h> 

int main() { 
    char s[]="AABAF"; 
    char *arr[20]; 
    int i; 
    for (i=0;i<20;i++) arr[i]=malloc(sizeof(s)); 
    calc(arr,s); 
    for (i=0;i<20;i++) printf("%d: %s\n",i,arr[i]); 
    return 0; 
} 
+0

Добавил несколько комментариев. больше предложений? – asaelr

+2

Наиболее важным улучшением, даже больше, чем комментариями, будут описательные имена функций/переменных. Сейчас у вас есть две функции с именем 'func' и' calc', а переменные с именем 'arr',' pref', 'pos',' adr', 'p',' l', 'i',' z', 'p',' s' и 'str'; ни одна из их целей не очевидна по их именам. Использование более описательных имен переменных сделает чудеса для удобочитаемости вашего кода. –

+1

Другие небольшие улучшения: используйте описательные типы ('z' должно быть' bool', '#include '); не используйте магические числа (размер 'arr', размер' p'); [не используйте 'strcpy()' для чего угодно, когда-либо] (http://stackoverflow.com/questions/1258550/why-should-you-use-strncpy-instead-of-strcpy); не забудьте называть 'free()' на вашем 'malloc()' s :) –

4

Использовать следующий рекурсивный алгоритм:

PermutList Permute(SymArray fullSymArray){ 
    PermutList resultList=empty; 
    for(each symbol A in fullSymArray, but repeated ones take only once) { 
     PermutList lesserPermutList= Permute(fullSymArray without A) 
     for (each SymArray item in lesserPermutList){ 
      resultList.add("A"+item); 
     } 
    } 
    return resultList; 
} 

Как вы видите, это очень легко

3

Я думаю, что эта проблема, по существу, проблема генерации многопозиционные перестановки. эта статья, по-видимому, актуальна: J. F. Korsh P. S. LaFollette. Генерация бесконечного массива многопозиционных перестановок. Computer Journal, 47 (5): 612-621, 2004.

Из статьи: Настоящий документ представляет собой алгоритм без петли для генерации всех перестановок мультимножества. Каждый из них получается из своего предшественника, делая одну транспозицию. Он отличается от предыдущих таких алгоритмов, используя массив для перестановок, но требующий хранения только линейного по своей длине.

+0

Молодцы, это похоже на это. –

+3

А как насчет того, чтобы попробовать написать сам? – Gangnus

3

Сначала преобразуйте строку в набор уникальных символов и номеров чисел, например. BANANA -> (3, A), (1, B), (2, N). (Это можно сделать путем сортировки строки и группировки букв). Затем для каждой буквы в наборе добавьте эту букву ко всем перестановкам набора с одним меньшим из этой буквы (обратите внимание на рекурсию). Продолжая пример «BANANA», мы имеем: перестановки ((3, A), (1, B), (2, N)) = A: (перестановки ((2, A), (1, B), (2 , N)) ++ B: (перестановки ((3, A), (2, N)) ++ N: (перестановки ((3, A), (1, B), (1, N))

Вот рабочая реализация в Haskell:

circularPermutations::[a]->[[a]] 
circularPermutations xs = helper [] xs [] 
          where helper acc [] _ = acc 
           helper acc (x:xs) ys = 
            helper (((x:xs) ++ ys):acc) xs (ys ++ [x]) 

nrPermutations::[(Int, a)]->[[a]] 
nrPermutations x | length x == 1 = [take (fst (head x)) (repeat (snd (head x)))] 
nrPermutations xs = concat (map helper (circularPermutations xs)) 
    where helper ((1,x):xs) = map ((:) x)(nrPermutations xs) 
     helper ((n,x):xs) = map ((:) x)(nrPermutations ((n - 1, x):xs)) 
1

Это сложный вопрос, и мы должны использовать рекурсию, чтобы найти все перестановки в строку, например, «AAB» перестановки будут «AAB», " ABA "и" BAA ". Нам также необходимо использовать Комплект, чтобы убедиться, что нет повторяющихся значений.

import java.io.*; 
import java.util.HashSet; 
import java.util.*; 
class Permutation { 

    static HashSet<String> set = new HashSet<String>(); 
    public static void main (String[] args) { 
    Scanner in = new Scanner(System.in); 
     System.out.println("Enter :"); 
     StringBuilder str = new StringBuilder(in.nextLine()); 
     NONDuplicatePermutation("",str.toString()); //WITHOUT DUPLICATE PERMUTATION OF STRING 
     System.out.println(set); 
    } 


    public static void NONDuplicatePermutation(String prefix,String str){ 
     //It is nlogn 
     if(str.length()==0){ 
      set.add(prefix); 
     }else{ 
      for(int i=0;i<str.length();i++){ 

       NONDuplicatePermutation(prefix+ str.charAt(i), str.substring(0,i)+str.substring(i+1)); 
      } 
     } 

    } 

} 
+0

Я написал свой код в java. Я думаю, что логика, приведенная в моем коде, в значительной степени понятна. – mukta

Смежные вопросы