我试图在c#中的所有组合中记住这个想法:
给定foo
这样的字符串,我希望得到一个List<string>
的值:
f o o
fo o
foo
f oo
正如你所看到的那样,并不像获取所有子字符串那么容易,而是将所有字符串都用空格分隔。
我尝试过这样的事情:
List<string> result = new List<string>();
string text = "foo";
for (int i = 1; i < foo.Lenght; i++)
{
//I'm stucked --> everything I think is too stupid and I don't know how to procede or not fast enough. I'm really stuck.
}
编辑: 有一些正确的答案,但很明显,他们中的任何一个都不会做,因为我正在使用的字符串各有55到85个字符,所以这意味着答案中的最佳功能会给我在2 ^ 54和2 ^ 84种可能的组合之间的东西,这只是有点太多了。
现在很清楚,找到所有的组合,之后与他们做一些事情不会做。我不得不放弃它。
答案 0 :(得分:5)
这是另一个需要考虑的递归解决方案:
private static IEnumerable<string> Permute(string target) {
if (target.Length <= 1) {
yield return target;
yield break;
}
var c = target[0];
foreach (var rest in Permute(target.Remove(0, 1))) {
yield return c + rest;
yield return c + " " + rest;
}
}
对于您的测试字符串产生所需的结果。基本上我们以递归的方式组合第一个字符+空格或没有空格+字符串的其余部分(没有第一个字符)。
要获取列表,只需执行Permute("foo").ToList();
对于“abcde”字符串,结果为:
abcde
a bcde
ab cde
a b cde
abc de
a bc de
ab c de
a b c de
abcd e
a bcd e
ab cd e
a b cd e
abc d e
a bc d e
ab c d e
a b c d e
答案 1 :(得分:4)
首先要做的事情是:如果字符串长度为 n ,则输出 2 ^ n 字符串。 所以,如果你想处理长度为70的字符串,你就会遇到问题。
您可以使用计数器,从 0 枚举到 2 ^ n ,并将其视为按位掩码:如果第一位为1,则放置一个空格在第一个和第二个字符之间,如果它为零,则不要。
因此,长度为64的无符号长度几乎不足以处理长度为65的字符串。
一个示例实现,没有递归(它比其他示例稍微冗长一些),但应该比其他长输入实现快得多:
public IEnumerable<string> GetPartitionedStrings(string s)
{
if (s == null) yield break;
if (s == "")
{
yield return "";
yield break;
}
if (s.Length > 63) throw new ArgumentOutOfRangeException("String too long...");
var arr = s.ToCharArray();
for(ulong i = 0, maxI = 1UL << (s.Length - 1); i < maxI; i++)
{
yield return PutSpaces(arr, i);
}
}
public string PutSpaces(char[] arr, ulong spacesPositions)
{
var sb = new StringBuilder(arr.Length * 2);
sb.Append(arr[0]);
ulong l = 1;
for (int i = 1; i < arr.Length; i++, l <<= 1)
{
if ((spacesPositions & l) != 0UL) sb.Append(" ");
sb.Append(arr[i]);
}
return sb.ToString();
}
可能你可以用一点点的字段,但我们已经在数十亿字符串中,所以我会尝试重新解决这个问题。
答案 2 :(得分:3)
你可以使用递归来做,从空字符串开始,递归调用添加空格而不添加空格,并添加当前字符:
static IEnumerable<string> SplitString(string s, int max)
{
return SplitString(s, 0, max, max);
}
private static IEnumerable<string> SplitString(string s, int idx, int available, int maxLength)
{
if (idx == s.Length) yield return string.Empty;
else
{
if (available > 0)
foreach (var item in SplitString(s, idx + 1, available - 1, maxLength))
yield return s[idx] + item;
if (idx > 0)
foreach (var item in SplitString(s, idx + 1, maxLength - 1, maxLength))
yield return " " + s[idx] + item;
}
}
对于abcde
之类的输入,SplitString("abcde", 3)
得到此输出:
abc de
abc d e
ab cde
ab cd e
ab c de
ab c d e
a bcd e
a bc de
a bc d e
a b cde
a b cd e
a b c de
a b c d e
答案 3 :(得分:3)
许多答案都提出了递归解决方案,这很好。但这是一个非递归解决方案的草图。
你能实现给出草图的方法吗?
答案 4 :(得分:-1)
你可以尝试一些递归的东西。您从字符串hello
开始。
对于不是空格的每个字符,如果它后面没有空格,则在字符串中的该位置添加一个并在该字符串上运行该函数。在第一次迭代中,您有:
h ello
he llo
hel lo
hell o
hello
重复,直到所有字符后跟空格。这会产生重复。
答案 5 :(得分:-2)
您可以做的是将字符串转换为char数组,如下所示:
char characters[] = text.toCharArray()
然后在你的for循环中迭代遍历这个数组
for (int i = 1; i < foo.Lenght; i++)
{
System.out.println(characters[i]);
}