假设我们有一个数字列表:
{1,3,7,13,19,54}
和单个值:17
在列表中找到最接近的2个数字围绕的最便宜的方法是什么?因此,在我们的示例中,答案为13
和19
。
目前,我正在使用循环来制作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))
这对我来说似乎很笨拙。所以我期待你!
答案 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));