Esto no utiliza LINQ pero funciona en tiempo lineal.
Supongo que la lista de entrada está ordenada.
Esto toma O(list.Count)
.
private static IEnumerable<int> get_miss(List<int> list,int length)
{
var miss = new List<int>();
int i =0;
for (i = 0; i < list.Count - 1; i++)
{
foreach (var item in
Enumerable.Range(list[i] + 1, list[i + 1] - list[i] - 1))
{
yield return item;
}
}
foreach (var item in Enumerable.Range(list[i]+1,length-list[i]))
{
yield return item;
}
}
Esto debe tomar O(n)
, donde n es la longitud del intervalo total.
static void Main()
{
List<int> identifiers = new List<int>() { 1, 2, 4, 7, 9 };
Stopwatch sw = new Stopwatch();
sw.Start();
List<int> miss = GetMiss(identifiers,150000);
sw.Stop();
Console.WriteLine("{0}",sw.ElapsedMilliseconds);
}
private static List<int> GetMiss(List<int> identifiers,int length)
{
List<int> miss = new List<int>();
int j = 0;
for (int i = 0; i < length; i++)
{
if (i < identifiers[j])
miss.Add(i);
else if (i == identifiers[j])
j++;
if (j == identifiers.Count)
{
miss.AddRange(Enumerable.Range(i + 1, length - i));
break;
}
}
return miss;
}
Como se indica en un comentario a Andras, un rango de 1 millón de enteros, y una lista de 100.000, con excepción (en mi máquina) toma 0.25 segundos. Pero no tenemos manera de saber si eso es lo suficientemente eficiente para usted (y si no, ¿cuáles son los límites de rendimiento aceptables?) –