2012-02-09 17 views
20

उत्पन्न किए बिना स्ट्रिंग के सभी अद्वितीय क्रमिकताओं को ढूंढना स्ट्रिंग के सभी क्रमपरिवर्तनों को ढूंढना एक प्रसिद्ध स्टीनहॉस-जॉनसन-ट्रॉटर एल्गोरिदम द्वारा है। लेकिन अगर स्ट्रिंग ऐसे
AABB के रूप में वर्ण दोहराए गए हैं,
तो संभव अद्वितीय संयोजन 4 हो जाएगा!/(2! * 2!) = 6डुप्लीकेट

इस को प्राप्त करने का एक तरीका यह है कि हम यह स्टोर कर सकते हैं है एक सरणी में या तो और डुप्लीकेट हटा दें।

क्या जॉनसन एल्गोरिदम को संशोधित करने का कोई आसान तरीका है, ताकि हम डुप्लिकेट किए गए क्रमपरिवर्तन उत्पन्न न करें। (सबसे कुशल तरीके से)

+0

क्रमपरिवर्तन की परिभाषा क्या है? क्या बीए एएबीबी का वैध क्रमपरिवर्तन है? – ElKamina

+2

कोई बीए एएबीबी का वैध क्रमपरिवर्तन नहीं है। – titan

+0

क्रमपरिवर्तन स्ट्रिंग में वर्णों को घुमाने का एक अनुक्रम है। लंबाई एन और अद्वितीय पात्रों की एक स्ट्रिंग के लिए हमारे पास कुल एन है! संभावित अद्वितीय क्रमपरिवर्तन – 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' नामक चर, 'पी',' एस', और 'str'; उनके किसी भी उद्देश्य उनके नाम से स्पष्ट नहीं हैं। अधिक वर्णनात्मक चर नामों का उपयोग करने से आपके कोड की पठनीयता के लिए आश्चर्य होगा। –

+1

अन्य छोटे सुधार: वर्णनात्मक प्रकारों का उपयोग करें ('z' 'bool' होना चाहिए,' # शामिल '); जादू संख्याओं का उपयोग न करें ('arr' का आकार,' p' का आकार); [किसी भी चीज़ के लिए 'strcpy() 'का उपयोग न करें] (http://stackoverflow.com/questions/1258550/why-should-you-use-strncpy-instead-of-strcpy); अपने 'malloc() 'के :) पर' free()' को कॉल करना न भूलें –

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

मुझे लगता है कि इस समस्या को अनिवार्य रूप से समस्या है मल्टीसेट क्रमपरिवर्तन उत्पन्न करने के लिए। यह पेपर प्रासंगिक प्रतीत होता है: जे एफ कोरश पी एस एस फोफलेट। मल्टीसेट क्रमपरिवर्तन के लूपलेस सरणी पीढ़ी । कंप्यूटर जर्नल, 47 (5): 612-621, 2004.

सार से: यह पत्र एक मल्टीसेट के सभी क्रमपरिवर्तन उत्पन्न करने के लिए एक लूपलेस एल्गोरिदम प्रस्तुत करता है। प्रत्येक को एक पूर्ववर्ती बनाकर अपने पूर्ववर्ती से प्राप्त किया जाता है। यह क्रमिक क्रम के लिए सरणी का उपयोग करके पिछले एल्गोरिदम से भिन्न है, लेकिन इसकी लंबाई में केवल भंडारण की आवश्यकता होती है।

+0

ठीक है, यह बिल्कुल वैसा ही दिखता है। –

+3

और इसे स्वयं लिखने और लिखने के बारे में क्या? – Gangnus

3

पहले स्ट्रिंग को अद्वितीय वर्णों और घटना संख्याओं के सेट में कनवर्ट करें। बनाना -> (3, ए), (1, बी), (2, एन)। (यह स्ट्रिंग और ग्रुपिंग अक्षरों को सॉर्ट करके किया जा सकता है)। फिर, सेट में प्रत्येक पत्र के लिए, उस पत्र को एक पत्र के एक कम से कम सेट के सभी क्रमिक क्रम में प्रस्तुत करें (रिकर्सन नोट करें)। "बनाना" उदाहरण जारी रखते हुए, हमारे पास है: क्रमपरिवर्तन ((3, ए), (1, बी), (2, एन)) = ए: (क्रमपरिवर्तन ((2, ए), (1, बी), (2 , एन)) ++ बी: (क्रमपरिवर्तन ((3, ए), (2, एन)) ++ एन: (क्रमपरिवर्तन ((3, ए), (1, बी), (1, एन))

यहाँ हास्केल में एक काम कर दिया गया है:

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" हो जाएगा, " एबीए "और" बीएए " हमें सेट करने की आवश्यकता है ताकि यह सुनिश्चित किया जा सके कि कोई डुप्लिकेट मान नहीं है।

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

मैंने जावा में अपना कोड लिखा था। मुझे लगता है कि मेरे कोड में दिया गया तर्क काफी समझा जाता है। – mukta

संबंधित मुद्दे