在数字列表中找到给定值周围最接近的两个数字的代价最低的方法是什么?

本文关键字:数字 两个 代价 是什么 方法 列表 最接近 周围 | 更新日期: 2023-09-27 18:11:45

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

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

和单个值:17

找到列表中值周围最接近的两个数字的最便宜的方法是什么?所以在我们的例子中,答案是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))

这对我来说似乎很笨拙。所以我指望你!

在数字列表中找到给定值周围最接近的两个数字的代价最低的方法是什么?

试试下面的代码:

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);

我希望这对你有帮助。

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

所以我的问题是:最快的代码(加上最少的内存)vs.最短的代码…你的问题没有提到这一点。

顺便说一句:处理极端情况并不容易。

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在阅读之前的注释后会接受这个答案:)

由于您没有指定如果单个值(17)没有较低或较高的值会发生什么,因此我将在这里让它们默认为NULL。

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

或者在一行中,尽管这样看起来更丑

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