【发布时间】:2010-11-07 20:39:32
【问题描述】:
如何使用 c# 找到 int 数组中的最小值
【问题讨论】:
标签: c#
如何使用 c# 找到 int 数组中的最小值
【问题讨论】:
标签: c#
使用 LINQ:
int min = theArray.Min();
请注意,如果没有 any 元素,这将出错;首先检查.Length(或者,投影到int?,但这会增加开销)。
如果您没有可用的 LINQ,那么可能:
public static int Min(int[] arr) {
switch (arr.Length) {
case 0: throw new InvalidOperationException();
case 1: return arr[0];
case 2: return Math.Min(arr[0], arr[1]);
default:
int min = arr[0];
for (int i = 1; i < arr.Length; i++) {
if (arr[i] < min) min = arr[i];
}
return min;
}
}
【讨论】:
case 2: return Math.Min(arr[0], arr[1]);默认你在做什么?
case 1: return arr[0];?
1或2的数组大小执行此操作,在case中无需执行此操作,您只需要一个简单的 if声明,但如果你说这样做是为了可读性,那是可以接受的。
.Min()...
我写了下面的内容来比较@Marc Gravell 所说的话,我告诉的方式在我的 PC 中要快一点,而 linq 是最慢的方式,此外,如果您更改函数的位置(在代码中),您将使用if 的版本总是会获得更好的性能
static void Main(string[] args)
{
Dictionary<string, List<long>> dic = new Dictionary<string, List<long>>();
dic["First"] = new List<long>();
dic["Second"] = new List<long>();
dic["Third"] = new List<long>();
for (int i = 0; i < 500; i++)
{
int[] array = GetRandomArray();
Stopwatch stopWacth = new Stopwatch();
stopWacth.Restart();
int n1 = FindMin(array);
stopWacth.Stop();
long firstTicks = stopWacth.ElapsedTicks;
dic["First"].Add(firstTicks);
stopWacth.Restart();
int n2 = AnotherFindMin(array);
stopWacth.Stop();
long secondTick = stopWacth.ElapsedTicks;
dic["Second"].Add(secondTick);
stopWacth.Restart();
int n3 = array.Min();
stopWacth.Stop();
long thirdTick = stopWacth.ElapsedTicks;
dic["Third"].Add(thirdTick);
Console.WriteLine("first tick : {0}, second tick {1}, third tick {2} ", firstTicks, secondTick, thirdTick);
}
Console.WriteLine("first tick : {0}, second tick {1}, third tick {2} ", dic["First"].Average(), dic["Second"].Average(), dic["Third"].Average());
Console.ReadLine();
}
public static int[] GetRandomArray()
{
int[] retVal = new int[1000000];
Random r = new Random();
for (int i = 0; i < 1000000; i++)
{
retVal[i] = r.Next(1000000000);
}
return retVal;
}
public static int FindMin(int[] arr)
{
switch (arr.Length)
{
case 0: throw new InvalidOperationException();
case 1: return arr[0];
case 2: return Math.Min(arr[0], arr[1]);
default:
int min = arr[0];
for (int i = 1; i < arr.Length; i++)
{
if (arr[i] < min) min = arr[i];
}
return min;
}
}
public static int AnotherFindMin(int[] arr)
{
if (arr.Length > 0)
{
int min = arr[0];
for (int i = 1; i < arr.Length; i++)
{
if (arr[i] < min) min = arr[i];
}
return min;
}
else
{
throw new InvalidOperationException();
}
}
}
// revised test by Marc (see comments discussion)
static class Test {
static void Main(string[] args)
{
Dictionary<string, List<long>> dic = new Dictionary<string, List<long>>();
dic["First"] = new List<long>();
dic["Second"] = new List<long>();
dic["Third"] = new List<long>();
const int OUTER_LOOP = 500, INNER_LOOP = 500000;
for (int arrSize = 1; arrSize <= 3; arrSize++)
{
for (int i = 0; i < OUTER_LOOP; i++)
{
int[] array = GetRandomArray(arrSize);
Stopwatch stopWacth = Stopwatch.StartNew();
for (int j = 0; j < INNER_LOOP; j++)
{
int n1 = FindMin(array);
}
stopWacth.Stop();
long firstTicks = stopWacth.ElapsedTicks;
dic["First"].Add(firstTicks);
stopWacth = Stopwatch.StartNew();
for (int j = 0; j < INNER_LOOP; j++)
{
int n2 = AnotherFindMin(array);
}
stopWacth.Stop();
long secondTick = stopWacth.ElapsedTicks;
dic["Second"].Add(secondTick);
stopWacth = Stopwatch.StartNew();
for (int j = 0; j < INNER_LOOP; j++)
{
int n3 = array.Min();
}
stopWacth.Stop();
long thirdTick = stopWacth.ElapsedTicks;
dic["Third"].Add(thirdTick);
//Console.WriteLine("{3}: switch : {0}, 0-check {1}, Enumerable.Min {2} ", firstTicks, secondTick, thirdTick, arrSize);
}
Console.WriteLine("{3}: switch : {0}, 0-check {1}, Enumerable.Min {2} ", dic["First"].Average(), dic["Second"].Average(), dic["Third"].Average(), arrSize);
}
Console.WriteLine("Done");
Console.ReadLine();
}
public static int[] GetRandomArray(int size)
{
int[] retVal = new int[size];
Random r = new Random();
for (int i = 0; i < retVal.Length; i++)
{
retVal[i] = r.Next(1000000000);
}
return retVal;
}
public static int FindMin(int[] arr)
{
switch (arr.Length)
{
case 0: throw new InvalidOperationException();
case 1: return arr[0];
case 2: return arr[0] < arr[1] ? arr[0] : arr[1];
default:
int min = arr[0];
for (int i = 1; i < arr.Length; i++)
{
if (arr[i] < min) min = arr[i];
}
return min;
}
}
public static int AnotherFindMin(int[] arr)
{
if (arr.Length > 0)
{
int min = arr[0];
for (int i = 1; i < arr.Length; i++)
{
if (arr[i] < min) min = arr[i];
}
return min;
}
else
{
throw new InvalidOperationException();
}
}
}
【讨论】:
Stopwatch 在一次迭代中不会给出有意义的答案;此外,此测试仅考虑default 情况(公平地说,这是最有可能的)。而且该数组如此非常大,以至于任何测试几乎没有显示来自这种逻辑选择的任何数字...
Restart - 那是你的扩展方法吗?我正在(本地)替换 Stopwatch.StartNew()
using System.Diagnostics;,重启不适合我,@Marc Gravell,你应该注意程序集跳转,这对我的方法来说更长