数组中的数字排列

时间:2015-10-23 22:46:20

标签: c# arrays algorithm linq permutation

我希望得到数组中所有可能的数字排列 - n!/ k!而n是数组的大小,k是相同数字的数量。

例如,[3,0,0]会有3(3!/ 2!)个可能的排列:

  • [3,0,0]
  • [0,3,0]
  • [0,0,3]

另一个例子是[2,1,0],它会产生6(3!/ 1!)个排列:

  • [2,1,0]
  • [1,2,0]
  • [0,1,2]
  • [0,2,1]
  • [2,0,1]
  • [1,0,2]

我已成功使用here中的代码:

static IEnumerable<IEnumerable<T>> 
    GetPermutationsWithRept<T>(IEnumerable<T> list, int length)
{
    if (length == 1) return list.Select(t => new T[] { t });
    return GetPermutationsWithRept(list, length - 1)
        .SelectMany(t => list, 
            (t1, t2) => t1.Concat(new T[] { t2 }));
}

生成排列后,我会运行Sum()来验证每个排列。然而,这可能不是一种有效的解决方案。还有另一种方法可以达到这个目的吗?

2 个答案:

答案 0 :(得分:0)

该函数接受一串字符,并记下该精确字符串的每个可能的排列,例如,如果&#34; ABC&#34;已经提供,应该溢出:

ABC,ACB,BAC,BCA,CAB,CBA。

代码:

enum Type_t

答案 1 :(得分:0)

使用Sum过滤GetPermutationsWithRept的输出不正确。考虑这种情况:

{1,2,3}

在这种情况下GetPermutationsWithRept的一个输出是{2,2}}。总和相等(2 + 2 + 2 = 1 + 2 + 3)。但是,{2,2,2}不是有效输出。

以下是基于您的方法的解决方案:

此类用于比较输出项(计算不同的结果):

public class EnumerableComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
    {
        return x.SequenceEqual(y);
    }

    public int GetHashCode(IEnumerable<T> obj)
    {
        return string.Join("-", obj.Select(x => x.ToString())).GetHashCode();
    }
}

以下代码调用GetPermutationsWithRept,并对结果进行两次过滤。第一次删除{3,3,3} ad {2,2,2}等无效项,第二次删除重复项。

var list = new int[] {1, 2, 3};

var result1 = GetPermutationsWithRept(list, 3).ToList();

var sorted_list = list.OrderBy(item => item).ToList();

var result2 = result1
    .Where(rlist => rlist.OrderBy(x => x).SequenceEqual(sorted_list)) //first filter
    .Distinct(new EnumerableComparer<int>()) //second filter
    .ToList();

我认为就性能而言,这种解决方案不适用于大型输入,但它是正确的。