【问题标题】:What is the best way to find the nearest lesser and greater values in a list to a given number在列表中找到与给定数字最近的较小和较大值的最佳方法是什么
【发布时间】:2014-04-25 05:54:05
【问题描述】:

我有一个随机的数字列表,例如 1、8、13、20、25、32、50、55、64、70,现在给定一个数字,例如 35,所需的较小值将是 32,较大的值将是 50。

我尝试这样做的方法是迭代所有值


        var value = 35;
        var list = new List<int> { 1, 8, 13, 20, 25, 32, 50, 55, 64, 70 };

        var lesser = list.First();
        var greater = list.Last();
        foreach (var curr in list)
        {
            if (curr >= value)
            {
                greater = curr;
                break;
            }
            lesser = curr;
        }

        Console.WriteLine("Lesser Value :{0}\tGreater Value:{1}", lesser, greater);

现在我问这个的原因是我需要针对列表生成一次然后多次请求值的情况进行优化。为每个请求迭代列表似乎是个坏主意。


更新

问题没有说明如果我们得到完全匹配需要什么,我需要上限和下限作为匹配的元素,即 32 应该返回 32 作为较小的值,32 作为较大的值以上列表。

反映相同的修改答案是:

int value = 32;
int[] list = new[] { 1, 8, 13, 20, 25, 32, 50, 55, 64, 70 };
int? floor = null;
int? ceil = null;
int index = Array.BinarySearch(list, value);
if (index >= 0) // element is found
{
    floor = ceil =list[index] ;
}
else
{
    index = ~index;
    if (index == list.Length)
    {
        ceil = floor = list[index-1];   
    }
    else
    {
        ceil = list[index];
        floor = list[((index==0)?index: index-1)];
    }
}
Console.WriteLine("floor = {0}", floor);
Console.WriteLine("ceil = {0}", ceil);

【问题讨论】:

  • 您对快速排序更感兴趣,还是对可读代码更感兴趣?如果可读,@Ehsan 的答案就是要走的路。如果速度快,也许是 Ulugbek 的
  • @paqogomez Ehsan 的代码实际上会导致迭代发生两次,而不是像我的代码中那样发生一次。到目前为止,Ulugbek 的答案是最好的选择。

标签: c# sequence


【解决方案1】:
int value = 35;
int[] list = new[] { 1, 8, 13, 20, 25, 32, 50, 55, 64, 70 };
int? floor = null;
int? ceil = null;
int index = Array.BinarySearch(list, value);
if (index >= 0) // element is found
{
    if (index > 0)
        floor = list[index - 1];
    if (index < list.Length - 1)
        ceil = list[index + 1];
}
else
{
    index = ~index;
    if (index < list.Length)
        ceil = list[index];
    if (index > 0)
        floor = list[index - 1];
}
Console.WriteLine("floor = {0}", floor);
Console.WriteLine("ceil = {0}", ceil);

【讨论】:

  • 好答案,实际上比我的表现更好..+1
【解决方案2】:

如果列表是排序的,你可以这样做:

int value = 35;
var lessThan = list.TakeWhile(p => p < value).LastOrDefault();
var greaterThan = list.SkipWhile(p => p <= value).FirstOrDefault();

【讨论】:

  • +0:您的代码与 OP 的代码基本相同(可能更易于阅读)。排序列表中的位置应该在 O(log n) 中找到,而不是 O(n)
  • 哪一部分?为什么你的线性搜索是 O(n) 或者二分搜索的复杂度是多少?
  • 这并不比目前的线性搜索好。
  • 我没有学过复杂性,我上次在大学里学过,现在我想我必须看看它
  • 您的解决方案是最具可读性的,但它确实为每个 value 迭代列表,并且 OP 专门询问了如何防止这种情况发生。
猜你喜欢
  • 2016-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-07
  • 2022-11-24
  • 2015-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多