获取开始和结束索引之间的数组最大值和最小值

时间:2014-07-16 15:48:52

标签: c# arrays max min

我需要一种简单,轻量级的方法来获得双精度数组的 max min 值。诀窍是我只需要数组中两个索引之间的最大值和最小值。

内置的 arrayOfDoubles.Max() arrayOfDoubles.Min()工作,因为它们会检查整个数组。

此代码将持续运行,并且需要有所效率。也就是说,简单性和可读性比速度更重要。

这是获得两个索引之间的最大值和最小值的一种方法:

double[] array = new double[8] { 3, 1, 15, 5, 11, 9, 13, 7 };

int startIndex = 3;
int endIndex = 6;

// Get max and min between these two indexes in the array
double max = GetMax(array, startIndex, endIndex);
double min = GetMin(array, startIndex, endIndex);

Console.WriteLine("Max = " + max + ", Min = " + min);

以下是 GetMax 的代码, GetMin 非常相似:

private static double GetMax(double[] array, int startIndex, int endIndex)
{
    double max = double.MinValue;

    for (int i = startIndex; i <= endIndex; i++)
    {
        // Increase max with each bigger value
        max = Math.Max(max, array[i]);
    }

    return max;
}

输出:Max = 13, Min = 5

问题:我可以通过哪些其他方式获得可能更简单并且不需要太多开销的相同结果?

5 个答案:

答案 0 :(得分:7)

var list = array.Skip(startIndex).Take(endIndex - startIndex + 1).ToList();
var min = list.Min();
var max = list.Max();

答案 1 :(得分:2)

您可以通过扫描一次数组来完成此操作。这是标准的最小/最大跟踪算法,在很多面试问题中提出,所以可读性不应成为问题。

void GetMinMax(double[] array, int start, int end, out double min, out double max)
{
    min = Double.MaxValue;
    max = Double.MinValue;

    // TODO: error checks for out-of-bounds, null, etc...
    for (int i = start; i <= end; ++i)
    {
        if (array[i] > max) max = array[i];
        if (array[i] < min) min = array[i];
    }
}

修改

使用Usman Zafar的answer来简化并消除多次错误检查的需要:

void GetMinMax(IList<double> list, out double min, out double max)
{
    // TODO: null/empty check for list.

    min = Double.MaxValue;
    max = Double.MinValue;

    for (int i = 0; i < list.Count; ++i)
    {
        if (list[i] > max) max = list[i];
        if (list[i] < min) min = list[i];
    }
}

现在使用任何IList<double>或您的情况下致电:new ArraySegment<double>(array, 3, 4)

答案 2 :(得分:2)

你也可以这样做:

var segment = new ArraySegment<double>(array, startIndex, endIndex - startIndex + 1);
var min = segment.Min();
var max = segment.Max();

答案 3 :(得分:2)

很明显,在未排序的数组中查找最小和最大元素需要O(n)算法,因为无论你如何操作,你都必须检查每个元素,至少一次。因此,您可以希望的唯一优化是特定于实现的,并且只能为常量带来收益。

然而,您可以使用一个聪明的技巧,仅使用3 * [n / 2]比较在阵列中找到最小值和最大值。虽然这不是渐近的改进,但与直接算法中所需的典型2 * n比较相比,它是n / 2的改进。因此,如果您希望执行大量的最小/最大计算,则可能值得将其视为一种选择。

你这样做是这样的:

  • 目前在两个变量
  • 中维护最小和最大元素
  • 在每次迭代时:
    • 比较彼此之间的下两个元素以确定哪一个更大
    • 将较大的元素与最大值进行比较(并在必要时进行交换)
    • 将较小的元素与最小值(并在必要时交换)
    • 进行比较

您将执行该循环的n / 2次迭代,并为每次迭代执行3次比较,总共执行3 * [n / 2]次操作。

这是一个实现:

void GetMinMax(double[] array, int start, int end, out double min, out double max)
{
    min = array[start];
    max = array[start];

    if((end - start) % 2 == 0)               // if there's an odd number of elements
       start = start + 1;                    //   skip the first one

    for (int i = start + 1; i <= end; i += 2)
    {
        if(array[i] > array[i-1])
        {
            if(array[i] > max) max = array[i];
            if(array[i - 1] < min) min = array[i - 1];
        } else {
            if(array[i - 1] > max) max = array[i - 1];
            if(array[i] < min) min = array[i];
        }
    }
}

答案 4 :(得分:-1)

使用LINQ的甜药:

        var res = array.Skip(startIndex).Take(1 + endIndex - startIndex );
        var min = res.Min();
        var max = res.Max();