【问题标题】:Find closest value algorithm查找最接近值算法
【发布时间】:2014-08-26 16:04:48
【问题描述】:
def find_closest(data, target, key = lambda x:f(x))

这是我的函数定义,其中数据是一组值,我想在尽可能少数次评估中找到评估最接近目标的值,即abs(target-f(x)) 是最小值。 f(x) 是单调的。

我听说二进制搜索可以在 O(log(n)) 时间内完成,python 中是否有库实现?有没有更高效的搜索算法?

编辑:我希望在评估 f(x) 方面尽量减少复杂性,因为那是昂贵的部分。我想找到用 f(x) 评估时最接近目标的数据中的 x。 dataf的域内,targetf的范围内。是的,数据可以快速排序。

【问题讨论】:

  • 您需要对 data 进行排序以具有 O(log(n)) 复杂度。在您的问题中描述data
  • 你的意思是lambda x:f(x)

标签: python algorithm search


【解决方案1】:

您可以使用bisect 模块中的实用程序。不过,您必须在 data 上评估 x,即 list(f(x) for x in data) 才能得到一个单调/排序的列表来平分。

我不知道标准库中有直接在fdata 上工作的二进制搜索。

【讨论】:

    【解决方案2】:

    如果呈现的数据已经排序并且函数是严格单调的, 对数据应用函数f,然后使用bisect.bisect进行二分查找

    import bisect
    def find_closest(data, target, key = f):
    
        data = map(f, data)
        if f(0) > f(1):
            data = [-e for e in data]
        try:
            return data[bisect.bisect_left(data, target)]
        except IndexError:
            return data[-1]
    

    【讨论】:

    • 首先查找不大于目标,同时请求最接近。
    • 使用了未定义的 f 变量
    【解决方案3】:

    使用bisect_left() 方法查找下限。 Bisect_left 接受随机访问的元素列表,为避免计算所有元素,您可以使用定义了 __len____getitem__ 方法的计算函数值的惰性集合。 仔细检查边界条件的返回值。 您的繁重计算将被称为O(log(N) + 1) = O(log(N)) 次。

    from bisect import bisect_left
    from collections import defaultdict
    
    class Cache(defaultdict):
        def __init__(self, method):
            self.method = method
        def __missing__(self, key):
            return self.method(key)
    
    class MappedList(object):
        def __init__(self, method, input):
            self.method = method
            self.input = input
            self.cache = Cache(method)
        def __len__(self):
            return len(self.input)
        def __getitem__(self, i):
            return self.cache[input[i]]
    
    def find_closest(data, target, key = lambda x:x):
        s = sorted(data)
        evaluated = MappedList(key, s)
        index = bisect_left(evaluated, target)
        if index == 0:
            return data[0]
        if index == len(data):
            return data[index-1]
        if target - evaluated[index-1] <= evaluated[index] - target:
            return data[index-1]
        else:
            return data[index]
    

    【讨论】:

    • 这看起来不错,不知道地图是懒惰的。在这里,您将返回 f(x),对,而不是 x。只需将其更改为return data[index]?
    • imap from your link 不支持随机访问
    • Check out mine。现在有了缓存! :) 我们的 6 元素输入数据只有两到三个计算。
    猜你喜欢
    • 1970-01-01
    • 2021-02-21
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2014-05-27
    相关资源
    最近更新 更多