给出类似" N00MNM"的字符串。我需要零' 0'的所有排列。字符串中的char以固定顺序维护所有其他字符。
结果必须是:
" N0M0NM" " N0MN0M" " N0MNM0" " NM00NM" " NM0N0M" " NM0NM0" " NMN0M0" " NMNM00" " 0N0MNM" " 0NM0NM" " 0NMN0M" " 0NMNM0"
标准排列函数花费了太多时间来完成这项工作(我们谈论的是大约1500毫秒)并且要测试的字符串比样本字符串长。
有这个算法吗?
答案 0 :(得分:0)
您可以通过获取可以放置字符0
(在这种情况下)的所有不同位置,然后包括0
个字符的总数来完成您要做的事情({{ 1}}在这种情况下)在字符串的所有位置。这些位置取自字符串而不会出现00
。下面的代码是这样做的:
0
public static IEnumerable<string> Combs(string str, char c)
{
int count = str.Count(_c => _c == c);
string _str = new string(str.Where(_c => _c != c).ToArray());
// Compute all combinations with different positions
foreach (var positions in GetPositionsSets(0, _str.Length, count))
{
StringBuilder _b = new StringBuilder();
int index = 0;
foreach (var _char in _str)
{
if (positions.Contains(index))
{ _b.Append($"{c}{_char}"); }
else
{ _b.Append(_char); }
index++;
}
if (positions.Contains(index))
_b.Append(c);
yield return _b.ToString();
}
//Compute the remaining combinations. I.e., those whose at some position
//have the amount of supplied characters.
string p = new string(c, count);
for (int i = 0; i < _str.Length; i++)
{
yield return _str.Insert(i, p);
}
yield return _str + p;
}
//Gets all posible positions sets that can be obtain from minPos
//until maxPos with positionsCount positions, that is, C(n,k)
//where n = maxPos - minPos + 1 and k = positionsCount
private static IEnumerable<HashSet<int>> GetPositionsSets(int minPos, int maxPos, int positionsCount)
{
if (positionsCount == 0)
yield return new HashSet<int>();
for (int i = minPos; i <= maxPos; i++)
{
foreach (var positions in GetPositionsSets(i + 1, maxPos, positionsCount - 1))
{
positions.Add(i);
yield return positions;
}
}
}
上面代码的输出是:
"N00MNM"