我想建立一个列表,其中包含单词大写的所有可能排列。所以它会是
List<string> permutate(string word)
{
List<string> ret = new List<string>();
MAGIC HAPPENS HERE
return ret;
}
所以说我加入“快乐”我应该得到一个
的数组{快乐,快乐,快乐,快乐,快乐,快乐...哈普,哈普,快乐,快乐}
我知道有很多功能会把第一个字母大写,但我该如何在字中做任意字母?
答案 0 :(得分:8)
如果将字符串转换为char数组,则可以修改单个字符。这样的事情应该可以解决问题...
public static List<string> Permute( string s )
{
List<string> listPermutations = new List<string>();
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<<j)) != 0
? char.ToUpper( array[j] )
: char.ToLower( array[j] );
listPermutations.Add( new string( array ) );
}
return listPermutations;
}
答案 1 :(得分:1)
请记住,虽然接受的答案是将任意字母大写的最直接方式,但如果要在同一组字母上重复更改大小写(例如,“快乐”中的32次并且指数级增长更长的单词),将字符串转换为char [],设置相应的字母,并从数组中构造字符串会更有效。
答案 2 :(得分:1)
要“置换”你的字符串(从技术上讲,这不是排列,因为你没有改变任何顺序,但我不想被视为一个* l-retentive :-),我会使用递归方法,它基本上“置换”字符串减去第一个字符,并将它们附加到该字符的上下变量。
有点像(在C中,我的C#并不是真的达到标准,所以你必须转换它):
#include <stdio.h>
#include <string.h>
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 <string to 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
答案 3 :(得分:1)
我能够创建一个执行此操作的控制台应用程序。
public static class Program
{
static void Main()
{
Console.WriteLine("Enter string");
string value = Console.ReadLine();
value = value.ToLower();
List<string> list = new List<string>();
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;
}
}
我得到了字符串中所有可能的字符子集的列表,然后为每个子集中的每个字符,用初始字符串中的大写字母替换了它们,然后列出了这些字符。必须具有自定义的替换功能作为普通字符串。替换将替换出现的任何字符。
这可能不是最干净的代码,但是可以完成工作。这是作为动态搜索加密字段的一种方式而提出的,我想看看那真的是多么疯狂。
答案 4 :(得分:0)
松散地说,如下所示。我可能会将我的范围缩小一个,但这个想法很合理。
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
答案 5 :(得分:0)
使用按位运算。对于长度为N的字,您需要一个由N位表示的整数类型。如果这个词更长 - 拆分它。迭代从0到2 N -1的值,并检查从0到N-1的每个位。如果该位为1 - upcase(Char.ToUpper()
)对应于该位的字母。
这种方法比递归算法更好,因为它不会在长字上出现堆栈溢出。
答案 6 :(得分:0)
假设:
1)你不太关心这是O(n * 2 ^ n)......虽然我很想知道:这类问题最好的渐近运行时间是什么?
2)您的输入全部为小写。
3)您的输入是&lt; 32个字符长。 (置换计数器中的可用位数,i)
List<string> permutate(string word)
{
List<string> ret = new List<string>();
// MAGIC HAPPENS HERE
Dictionary<char,char> toUppers = new Dictionary<char,char>(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;
}
注意:我没有编译或测试此代码。这也是实现上面提到的尖锐的比较。
答案 7 :(得分:0)
如果顺序无关紧要,则可以尝试 Linq 。我们列举了[0..2**word.Length]
范围内的所有二进制数。并将每个数字视为 mask :0
-小写,1
-大写。我们拥有的happy
的FDor实例
mask string
----------------
00000 -> happy
00001 Happy
00010 hAppy
00011 HAppy
00100 haPpy
00101 HaPpy
...
11111 HAPPY
代码:
using System.Linq;
...
List<string> permutate(string word) =>
Enumerable
.Range(0, 1 << word.Length)
.Select(mask => string.Concat(word.Select((c, i) => (mask & (1 << i)) == 0
? char.ToLower(c)
: char.ToUpper(c))))
.ToList();
演示:
Console.Write(string.Join(", ", permutate("happy")));
结果:
happy, Happy, hAppy, HAppy, haPpy, HaPpy, hAPpy, HAPpy, hapPy, HapPy, hApPy, HApPy, haPPy, HaPPy, hAPPy, HAPPy, happY, HappY, hAppY, HAppY, haPpY, HaPpY, hAPpY, HAPpY, hapPY, HapPY, hApPY, HApPY, haPPY, HaPPY, hAPPY, HAPPY