因此,我正在进行在线测试,其中我必须实现一段代码来简单地检查该值是否在数组中。我写了以下代码:
using System;
using System.IO;
using System.Linq;
public class Check
{
public static bool ExistsInArray(int[] ints, int val)
{
if (ints.Contains(val)) return true;
else return false;
}
}
现在我在这里没有看到任何问题,因为代码可以正常工作,但是由于数组包含百万个值,这样做“不够快”,所以我仍然无法通过测试。
我自己编写的唯一代码是:
if (ints.Contains(val)) return true;
else return false;
我可以使用的其他代码。
有没有办法加快这个过程?
谢谢。
编辑: 我碰到了一个页面,其中有人显然接受了与我相同的测试,这似乎可以节省CPU周期。
参考:How to save CPU cycles when searching for a value in a sorted list?
现在他在方法中的解决方案是:
var lower = 0;
var upper = ints.Length - 1;
if ( k < ints[lower] || k > ints[upper] ) return false;
if ( k == ints[lower] ) return true;
if ( k == ints[upper] ) return true;
do
{
var middle = lower + ( upper - lower ) / 2;
if ( ints[middle] == k ) return true;
if ( lower == upper ) return false;
if ( k < ints[middle] )
upper = Math.Max( lower, middle - 1 );
else
lower = Math.Min( upper, middle + 1 );
} while ( true );
现在我明白了这段代码是如何工作的,但是我不清楚为什么这应该更快。如果有人可以详细说明会很好。
答案 0 :(得分:8)
如果是已排序的数组,则可以使用 BinarySearch 来加快过程
public static bool ExistsInArray(int[] ints, int val)
{
return Array.BinarySearch(ints, val) >= 0;
}
答案 1 :(得分:0)
如果输入数组已经排序,则最好使用BinarySearch。
.NET通过使用Array.BinarySearch方法内置了对BinarySearch的支持。
只需对包含和100万个整数值的排序数组进行包含和BinarySearch的快速实验即可。
public static void Main()
{
var collection = Enumerable.Range(0, 1000000).ToArray();
var st = new Stopwatch();
var val = 999999;
st.Start();
var isExist = collection.Contains(val);
st.Stop();
Console.WriteLine("Time taken for Contains : {0}", st.Elapsed.TotalMilliseconds);
t.Restart();
var p = BinarySearchArray(collection, 0, collection.Length - 1, val);
st.Stop();
if(p == -1)
{
Console.WriteLine("Not Found");
}
else
{
Console.WriteLine("Item found at position : {0}", p);
}
Console.WriteLine("Time taken for binary search {0}", st.Elapsed.TotalMilliseconds);
}
private static int BinarySearchArray(int[] inputArray, int lower, int upper, int val)
{
if(lower > upper)
return -1;
var midpoint = (upper + lower) / 2;
if(inputArray[midpoint] == val)
{
return midpoint;
}
else if(inputArray[midpoint] > val)
{
upper = midpoint - 1;
}
else if(inputArray[midpoint] < val)
{
lower = midpoint+1;
}
return BinarySearchArray(inputArray, lower, upper, val);
}
以下是输出。
Time taken for Contains : 1.0518
Item found at position : 999999
Time taken for binary search 0.1522
很明显,BinarySearch在这里占了上风。
.NET的Contains方法在内部不使用BinarySearch。包含对于较小的集合很有用,但对于较大的数组,BinarySearch是更好的方法。
答案 2 :(得分:-1)
您可以使用Parallel,类似于以下代码:
namespace ParallelDemo
{
class Program
{
static void Main()
{
var options = new ParallelOptions()
{
MaxDegreeOfParallelism = 2
};
List<int> integerList = Enumerable.Range(0,10).ToList();
Parallel.ForEach(integerList, options, i =>
{
Console.WriteLine(@"value of i = {0}, thread = {1}",
i, Thread.CurrentThread.ManagedThreadId);
});
Console.WriteLine("Press any key to exist");
Console.ReadLine();
}
}
}
注意:它将加快速度,但是您将使用更多的内存
答案 3 :(得分:-1)
正确的答案是:取决于。
最简单的答案是Linq,尽管它的全部奇迹实际上是相当缓慢的。它需要大量反射,并且通常会在幕后执行大量工作。当易读性是您的主要目标时,这很棒。但是为了表现?不。
在单线程,未排序的列表中,老式的for循环将为您带来最佳效果。如果已排序,则二进制搜索或快速搜索的某些版本将是最佳的选择。
对于并行,C#具有并行类。但是请注意,如果列表足够小,则创建线程的开销可以克服您的搜索时间。
简单的单线程未排序答案:
public static bool ExistsInArray(int[] ints, int val)
{
for( int index = 0, count = ints.GetLowerBound(0); index < count; ++index)
{
if (ints[index] == val) return true;
}
return false;
}
您正在寻找的网站很可能想要这个。但这仅在数组已排序的情况下有效。
public static bool ExistsInArray(int[] ints, int val)
{
return Array.BinarySearch(ints, val) > 0;
}
证明Linq不够快的辅助帖子。