确定整数列表中的第一个可用值

时间:2012-01-14 22:12:49

标签: c# linq collections

我得到了一个简单的整体列表。

List<int> myInts = new List<int>();

myInts.Add(0);
myInts.Add(1);
myInts.Add(4);
myInts.Add(6);
myInts.Add(24);

我的目标是从列表中获取第一个未使用的(可用)值。

(集合中尚未出现的第一个正值)

在这种情况下,答案是2。

这是我目前的代码:

int GetFirstFreeInt()
{
    for (int i = 0; i < int.MaxValue; ++i)
    {
        if(!myInts.Contains(i))
            return i;
    }

    throw new InvalidOperationException("All integers are already used.");
}

有更好的方法吗?也许使用LINQ?你会怎么做?

当然,为了简单起见,我使用了int,但我的问题适用于任何类型。

2 个答案:

答案 0 :(得分:18)

您基本上需要0..int.MaxValue中未包含的序列myInts中的第一个元素:

int? firstAvailable = Enumerable.Range(0, int.MaxValue)
                                .Except(myInts)
                                .FirstOrDefault();

编辑以回复评论:

此处有性能损失,以迭代int.MaxValue。 Linq将在内部创建的是一个哈希表myInts,然后开始迭代Enumerable.Range()创建的序列 - 一旦哈希表中未包含的第一个项被发现整数由Except()产生{1}}方法并由FirstOrDefault()返回 - 之后迭代停止。这意味着整体努力是O(n)用于创建哈希表,然后是最坏情况O(n)用于迭代序列,其中n是myInts中的整数数。

有关Except()的详情,请参阅Jon Skeet的EduLinq系列:Reimplementing LINQ to Objects: Part 17 - Except

答案 1 :(得分:2)

好吧,如果列表从最小到最大排序并且包含从0到正无穷大的值,则可以简单地访问第i个元素。 if (myInts[i] != i) return i;本质上是相同的,但不需要在每个Contains检查中遍历列表(Contains方法遍历列表,将算法转换为O(n平方)而不是O(n))。