在数字列表中找到围绕给定值的两个最接近数字的最便宜的方法是什么?

时间:2016-10-05 18:56:52

标签: c# vb.net

假设我们有一个数字列表:

{1,3,7,13,19,54}

和单个值:17

在列表中找到最接近的2个数字围绕的最便宜的方法是什么?因此,在我们的示例中,答案为1319

目前,我正在使用循环来制作2个列表,其中一个是上面的数字,另一个是下面的数字。然后我用这样的东西:

point1 = pointsAbove.Aggregate(Function(x, y) If(Math.Abs(x.X - xVal) < Math.Abs(y.X - xVal), x, y))
point2 = pointsBelow.Aggregate(Function(x, y) If(Math.Abs(x.X - xVal) < Math.Abs(y.X - xVal), x, y))

这对我来说似乎很笨拙。所以我期待你!

3 个答案:

答案 0 :(得分:3)

尝试以下代码:

List<int> numbers = new List<int>(){ 6, 7, 8, 9, 1, 2, 3, 4, 5 };
int middle = 6;

var min = numbers.Where(y => y < middle).Max(); // min = 5
var max = numbers.Where(y => y > middle).Min(); // max = 7

上面的代码适用于已排序和未排序的列表。

如果你不能确定你有至少一分钟和/或一个最大值,你必须这样做,否则你会得到一个例外:

var min = numbers.Where(y => y < middle).DefaultIfEmpty().Max(); 
var max = numbers.Where(y => y > middle).DefaultIfEmpty().Min();

并且,如果您确定100%的时间列表已排序,您可以在下面的代码中保存一些性能:

var min = numbers.LastOrDefault(y => y < middle); 
var max = numbers.FirstOrDefault(y => y > middle);

我希望它对你有所帮助。

答案 1 :(得分:2)

假设您的列表已排序,您无需及时迭代O(n)列表。使用二进制搜索可以在O(log(n))中处理。

所以我的问题是:最快的代码(加上最少的内存)和最短的代码...你的问题没有说明任何事情......

BTW:处理角落案件并不容易..

var list = new List<int> { 1, 3, 7, 13, 20, 54 };
var numToSearch = 54;
int point1 = int.MinValue, point2 = int.MinValue;

var inx = list.BinarySearch(numToSearch); //<---


if (inx >= 0) //search item is in the list
{
    if (inx == 0)
    {
        point1 = list[0];
        point2 = list[1];
    }
    else if (inx == list.Count - 1)
    {
        point1 = list[inx - 1];
        point2 = list[inx];
    }
    else
    {
        int val1 = list[inx - 1];
        int val2 = list[inx + 1];

        if (Math.Abs(val1 - list[inx]) < Math.Abs(list[inx] - val2))
        {
            point1 = list[inx - 1];
            point2 = list[inx];
        }else
        {
            point1 = list[inx];
            point2 = list[inx+1];
        }
    }
}
else {
    point1 = list[~inx - 1];
    point2 = list[~inx];
}

PS:最少时间?最少的记忆?最少代码?很难同时实现(如果不是不可能)。似乎OP会随机回答:)

PS2:在阅读之前的笔记后,我不希望OP会接受这个答案:)

答案 2 :(得分:0)

由于你没有指定如果你的单个值(17)没有更高的值更低会发生什么,我会在这里默认为NULL。

int number = 17; 
int? lower = points.LastOrDefault(x => x < number);
int? upper = points.FirstOrDefault(x => x > number);

或者在一行中,尽管这是更加丑陋的imo

Tuple<int?, int?> closestNumbers = new Tuple<int?, int?>(points.LastOrDefault(x => x < number), points.FirstOrDefault(x => x > number));