【问题标题】:List of Numbers - How to Efficiently Find Largest Less Than or Equal to N [duplicate]数字列表 - 如何有效地找到小于或等于 N 的最大值 [重复]
【发布时间】:2013-06-07 17:06:23
【问题描述】:

假设我有一组恰好被排序的固定数字:

static readonly int[] numbers = new int {
    1, 200, 204, 228, 298, 300, 331, 332, ... 2983
};

如何有效地找到小于或等于任意值的最大数。我正在尝试创建的功能如下:

public int LessThanOrEqualTo(int n)
{
    // ???
}

最简单的方法是每次迭代集合。但是,我正在寻找一种方法来加快速度。我可以将其转换为另一种格式,例如 IDictionary,但想不出一个聪明的方法来临时做这个。

【问题讨论】:

  • 二分查找?
  • 注意“如果找到 item;否则,一个负数,它是下一个大于 item 的元素的索引的按位补码”,因此如果没有找到,你会得到下一个更大的,并且因此,您可以向后移动一个索引以获取您想要的元素。 msdn.microsoft.com/en-us/library/5kwds4b1.aspx
  • @AaronLS 请注意,在这种情况下,它将是 Array.BinarySearch 而不是列表版本。
  • 这并不完全是二分搜索,尽管合并二分搜索可能是个好主意。
  • @MattGreer 实际上,这是完全二分搜索。

标签: c# algorithm


【解决方案1】:

如果您无法控制列表的生成,二进制搜索可能是您的最佳选择

*注意:这是伪代码,并不打算涵盖所有边缘条件

FindLargestLessThan(int val, int[] arr, int hi, int lo)
{
    if(hi == lo)
    {
        // it's either arr[hi] or the element immediately before that.
    }
    else if(arr[(hi+lo)/2] > val)
    {
        return FindLargestLessThan(val, arr, (hi+lo)/2, lo)
    }
    else if(arr[(hi+lo)/2] < val)
    {
        return FindLargestLessThan(val, arr, hi, (hi+lo)/2)
    }
    else if(arr[(hi+lo)/2] == val)
    {
        //found it
    }
    else
    {
        //oops
    }
}

【讨论】:

  • 如果您确实可以控制列表的生成,您会采取什么不同的做法?
  • @Servy 你可以做一些散列实现
  • 并非如此。散列是为了找到精确的值,而不是“接近”的值。任何时候你想要找到满足除相等哈希之外的某些条件的值时,除了最罕见的情况外,它往往会崩溃。
【解决方案2】:

回答了一个非常相似的问题here

使用 Array.BinarySearch。如果输入在列表中,它将返回索引,如果不是,则返回第一个较大值的索引的补码。您只需反转结果并减去一个以获得最接近的较小值的索引。

【讨论】:

  • 这不仅是相似的,而且是完全一样的骗局。在这种情况下,您可以投票/标记关闭。
  • @Servy 有一个非常小的差异。 &lt;=&lt;.
  • 我不知道该怎么做。我是新来的。从现在开始我会的,谢谢。
猜你喜欢
  • 2021-06-09
  • 2016-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 2021-02-24
相关资源
最近更新 更多