【问题标题】:Most efficient way to find the nearest number in a list在列表中查找最近数字的最有效方法
【发布时间】:2015-05-22 05:23:01
【问题描述】:

我知道他们在说什么预优化是万恶之源,但是我更想知道什么是最有效的方法。知识库再多一点,你知道吗?

基本上我有一个整数集合,如下所示:

final List<Integer> list = ImmutableList.of(1, 5, 10, 27, 57, 193);

现在我想找到最接近的数字,向下取整。例如,我有数字 192。所以这个列表的返回值将是“57”。如果数字是 58,同样适用。它只是找到下一个最小的数字。

目前我正在从末尾开始循环列表,使用for 然后返回列表的索引,这将是我想要的数字。我只是好奇是否有更有效的方法来做到这一点。

【问题讨论】:

  • 列表排序了吗?这是为了一致的哈希吗?
  • 您听说过快速排序吗?
  • 据我所知,通过大 O 表示法,单个循环非常有效。只需返回减法的绝对值和 bam,最接近的数字索引。
  • Collections.binarySearch 是要走的路。如果列表未排序,请先使用Collections.sort
  • @SeçkinSavaşçı:如果您只需要一次号码,那并不是最快的。

标签: java


【解决方案1】:

通用列表

如果对列表一无所知,遍历列表并记住当前最佳解决方案确实是最有效的。

但是,如果您计划进行数千次这样的查询,您可以先对列表进行排序。

排序列表

如果列表已排序,您可以使用binarySearch(List&lt;? extends Comparable&lt;? super T&gt;&gt; list, T key) 方法。此方法返回新元素的插入点。如果元素存在,则返回该元素的正索引。否则返回插入索引的位否定

然后你可以调用它:

//only to be used if list is sorted (a priori)
public int closestValue (List<Integer> list, int value) {
    int index = Collections.binarySearch(list,value);
    if(index < 0) {
        index = ~index-1;
    }
    return list.get(index);
}

jdoodle demo.

如果没有这样的元素,该方法将抛出IndexOutOfBoundsException

二分查找可以在 O(log n) 内完成,但只有 - 如前所述 - 如果列表已排序。

【讨论】:

    【解决方案2】:

    如果列表是排序的,那么你可以对列表进行二分搜索,你可以在 Log(n) 中得到你的 no。

    【讨论】:

      【解决方案3】:

      您可以对列表进行排序,然后使用类似二进制搜索的方法来查找最近的数字。

      【讨论】:

        【解决方案4】:

        创建一个最大值大小的 HashMap,然后用预期结果的密钥对填充映射。即 map.put(6,5);map.put(7,5) 等等。

        之后得到正确的值将在 O(1) 中。

        当然,地图的创建需要更多的时间和资源,但在无限长的时间内,这将产生最快的结果。

        【讨论】:

        • 这行不通,因为查询可以是任何东西:您可以查询2'000'000'000+:您要构建一个包含超过 4GiB 元素的哈希图?会带走所有的记忆。此外,在最坏的情况下,hashmap 的时间复杂度为 O(n)。此外,setup 设置阶段将花费大量时间。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-23
        • 1970-01-01
        • 1970-01-01
        • 2018-03-11
        相关资源
        最近更新 更多