Я получил немного вдохновения и подумал о решении, ориентируясь только на скорость. Это действительно не так хорошо читается (что я обычно предпочитаю), но характеристики, когда речь идет о скорости, должны быть довольно хорошими.
В худшем случае то же самое для большинства других реализаций O (n), но это маловероятно, поскольку для этого потребуется, чтобы все первая половина элементов была равна , а - вторая половина для всех быть равным, но не равным значению в первой половине.
и потребует того же числа сравнений, что и линейный поиск.
В большинстве других случаев с первым нечетным в случайном месте это потребует вдвое меньше сравнений, чем линейное.
В случае, если значения в парах. Так что item [0] == item [1] и item [2] == item [3] и item [0]! = Item [2] (и аналогичные) тогда линейный поиск будет быстрее.
Как правило, со случайными данными или несколькими нечетными один раз это должно быть быстрее, чем линейный поиск
public static bool AllSame<T>(this IEnumerable<T> source,
IEqualityComparer<T> comparer = null)
{
if (source == null)
throw new ArgumentNullException("source cannot be null.", "source");
if (comparer == null)
comparer = EqualityComparer<T>.Default;
var enumerator = source.GetEnumerator();
return source.Zip(comparer);
}
private static bool Zip<T>(this IEnumerable<T> sequence, IEqualityComparer<T> comparer)
{
var result = new List<T>();
var enumerator = sequence.GetEnumerator();
while (enumerator.MoveNext())
{
var first = enumerator.Current;
result.Add(enumerator.Current);
if (enumerator.MoveNext())
{
if (!comparer.Equals(first, enumerator.Current))
{
return false;
}
}
else
{
break;
}
}
return result.Count == 1 ? true : result.Zip(comparer);
}
без оптимизации хвостового вызова при этом используется дополнительная память (в худшем случае объем памяти близок к объему памяти, используемому для исходного источника). Хотя стек вызовов не должен доходить до глубины, поскольку никакие конкретные реализации IEnumerable (по крайней мере, я об этом знаю) не могут содержать больше, чем элементы int.MaxValue. который потребует максимум 31 рекурсию.