资本化的排列

我想建立一个列表,其中包含一个单词大写的每个可能的排列。 所以它会

List permutate(string word) { List ret = new List(); MAGIC HAPPENS HERE return ret; } 

所以说我加入“快乐”我应该得到一个arrays

{快乐,快乐,快乐,快乐,haPpy,HaPpy ……哈普,哈普,快乐,快乐}

我知道有很多函数可以将第一个字母大写,但是如何在单词中做任意字母?

如果将字符串转换为char数组,则可以修改单个字符。 像这样的东西应该做的伎俩……

 public static List Permute( string s ) { List listPermutations = new List(); char[] array = s.ToLower().ToCharArray(); int iterations = (1 << array.Length) - 1; for( int i = 0; i <= iterations; i++ ) { for( int j = 0; j < array.Length; j++ ) array[j] = (i & (1< 

请记住,虽然接受的答案是将任意字母大写的最直接方式,但如果要在同一组字母上重复更改大小写(例如,“快乐”中为32次,对于较长的单词则呈指数级增长) ,将字符串转换为char [],设置相应的字母,并从数组中构造字符串会更有效。

要“置换”你的字符串(从技术上讲,这不是排列,因为你没有改变任何顺序,但我不想被视为一个* l-retentive :-),我会使用递归方法,它基本上“置换”字符串减去第一个字符,并将它们附加到该字符的上下变量。

有点像(在C中,我的C#并不是真的达到标准,所以你必须转换它):

 #include  #include  static void permute (char *prefix, char *str) { char *newPrefix; /* End of string, print and return. */ if (*str == '\0') { printf ("%s\n", prefix); return; } /* Allocate space for new prefix. */ if ((newPrefix = malloc (strlen (prefix) + 2)) == NULL) { printf ("ERROR: Cannot allocate memory.\n"); return; } /* Do lowercase/sole version and upper version if needed. */ sprintf (newPrefix, "%s%c", prefix, *str); permute (newPrefix, &(str[1])); if (islower (*str) { sprintf (newPrefix, "%s%c", prefix, toupper(*str)); permute (newPrefix, &(str[1])); } /* Free prefix and return. */ free (newPrefix); } 

 int main (int argc, char *argv[]) { char *str, *strPtr; /* Check and get arguments. */ if (argc < 2) { printf ("Usage: permute \n"); return 1; } if ((str = malloc (strlen (argv[1]) + 1)) == NULL) { printf ("ERROR: Cannot allocate memory.\n"); return 1; } strcpy (str, argv[1]); /* Convert to lowercase. */ for (strPtr = s; *strPtr != '\0'; strPtr++) *strPtr = toupper (*strPtr); /* Start recursion with empty prefix. */ permute ("", str); /* Free and exit. */ free (str); return 0; } 

将此作为"permute Pax1"运行会返回:

 pax1 paX1 pAx1 pAX1 Pax1 PaX1 PAx1 PAX1 

我能够创建一个控制台应用程序来做到这一点..

  public static class Program { static void Main() { Console.WriteLine("Enter string"); string value = Console.ReadLine(); value = value.ToLower(); List list = new List(); var results = from e in Enumerable.Range(0, 1 << value.Length) let p = from b in Enumerable.Range(0, value.Length) select (e & (1 << b)) == 0 ? (char?)null : value[b] select string.Join(string.Empty, p); foreach (string s in results) { string newValue = value; s.ToLower(); foreach(char c in s) { var Old = c.ToString().ToLower(); var New = c.ToString().ToUpper(); newValue=ReplaceFirstOccurrence(newValue, Old, New); } list.Add(newValue); } foreach(string s in list) { Console.WriteLine(s); } Console.ReadKey(); } public static string ReplaceFirstOccurrence(string Source, string Find, string Replace) { int Place = Source.IndexOf(Find); string result = Source.Remove(Place, Find.Length).Insert(Place, Replace); return result; } } 

松散地说,像下面这样的东西。 我可能会把我的范围缩小一个,但这个想法是合理的。

 def cap_n(in_str, pos): leading = in_str.substr(0, pos-1) trailing = in_str.substr(pos+1) # no second arg implies to end of string chr = in_str[pos].to_uppercase() return leading + chr + trailing 

使用按位运算。 对于长度为N的字,您需要一个由N位表示的整数类型。 如果这个词更长 – 拆分它。 迭代0到2 N -1之间的值,并检查从0到N-1的每个位。 如果该位为1 – upcase( Char.ToUpper() )对应于该位的字母。

这种方法比递归算法更好,因为它不会在长字上出现堆栈溢出。

假设:

1)你不太关心这是O(n * 2 ^ n)……虽然我很想知道:这类问题的最佳渐近运行时间是多少?

2)您的输入全部为小写。

3)您的输入长度<32个字符。 (置换计数器中的可用位数,i)

  List permutate(string word) { List ret = new List(); // MAGIC HAPPENS HERE Dictionary toUppers = new Dictionary(26); toUppers.Add('a', 'A'); toUppers.Add('b', 'B'); toUppers.Add('c', 'C'); toUppers.Add('d', 'D'); toUppers.Add('e', 'E'); toUppers.Add('f', 'F'); toUppers.Add('g', 'G'); toUppers.Add('h', 'H'); toUppers.Add('i', 'I'); toUppers.Add('j', 'J'); toUppers.Add('k', 'K'); toUppers.Add('l', 'L'); toUppers.Add('m', 'M'); toUppers.Add('n', 'N'); toUppers.Add('o', 'O'); toUppers.Add('p', 'P'); toUppers.Add('q', 'Q'); toUppers.Add('r', 'R'); toUppers.Add('s', 'S'); toUppers.Add('t', 'T'); toUppers.Add('u', 'U'); toUppers.Add('v', 'V'); toUppers.Add('w', 'W'); toUppers.Add('x', 'X'); toUppers.Add('y', 'Y'); toUppers.Add('z', 'Z'); char[] wordChars = word.ToCharArray(); int len = wordChars.Length; // iterate the number of permutations for(int i = 0; i < 2^len; i++) { char[] newWord = new char[len](); // apply "i" as a bitmask to each original char for(int n = 0; n < newWord.Length; n++) { if((1 << n) & i != 0) { newWord[n] = toUppers[wordChars[n]]; // or skip the dictionary and just call Char.ToUpper(wordChars[n]) } else { newWord[n] = wordChars[n]; } } ret.Add(new String(newWord)); } return ret; } 

注意:我没有编译或测试此代码。 这也是实现上面提到的尖锐的比较。