c# – 如何快速判断一个列表是否只包含重复项?

有多个相关问题,但我正在寻找一个与我的案例相关的解决方案.有一个(通常)14个整数的数组.如何快速判断每个int是否出现两次(即有7对)?值范围从1到35.这里的主要方面是性能.

作为参考,这是我目前的解决方案.它的写作类似于规范,尽可能的紧密,不考虑性能,所以我肯定可以大大改进:

var pairs = Array
    .GroupBy (x => x)
    .Where (x => x.Count () == 2)
    .Select (x => x.ToList ())
    .ToList ();
IsSevenPairs = pairs.Count == 7;

使用Linq是可选的.我不在乎如何,只要它很快:)

编辑:有一个特殊情况,int出现2n次,n>在这种情况下,支票应该失败,即应该有7个不同的对.

编辑:结果
我测试了Ani和Jon的解决方案,并在目标应用程序中的多个基准测试中发现,Ani’s在我的机器上有两倍的吞吐量(Win7-64上的一些Core 2 Duo).生成int数组已经需要与相应的检查一样长的时间,所以我对结果感到满意.谢谢,所有!

解决方法

显然,LINQ不会在这里提供最佳解决方案,尽管我将改进您当前的LINQ解决方案:
// checks if sequence consists of items repeated exactly once
bool isSingleDupSeq = mySeq.GroupBy(num => num)
                           .All(group => group.Count() == 2);

// checks if every item comes with atleast 1 duplicate
bool isDupSeq = mySeq.GroupBy(num => num)
                     .All(group => group.Count() != 1);

对于具体情况,您提到(0 – 31),这是一个快速的基于阵列的解决方案.当可能数字的范围很大(在这种情况下使用散列解决方案))时,它不会很好地扩展.

// elements inited to zero because default(int) == 0
var timesSeenByNum = new int[32];

foreach (int num in myArray)
{
    if (++timesSeenByNum[num] == 3)
    {
        //quick-reject: number is seen thrice
        return false;
    }
}

foreach (int timesSeen in timesSeenByNum)
{
    if (timesSeen == 1)
    {
        // only rejection case not caught so far is
        // if a number is seen exactly once
        return false;
    }
}

// all good,a number is seen exactly twice or never
return true;

编辑:修正了Jon Skeet指出的错误.我也应该指出,他的算法更聪明,也许更快.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...