java—在比较器的值由函数调用生成的大范围内,如何使用二进制搜索?

vs91vp4v  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(271)

关闭。这个问题需要更加突出重点。它目前不接受答案。
**想改进这个问题吗?**通过编辑这篇文章更新这个问题,使它只关注一个问题。

上个月关门了。
改进这个问题
我有一个非常大的连续自然数列表,从0到109。我们将此数组中的每个索引都称为键。有一个单调递增的函数f(key),它为每个key生成一个值。我想找到对应于给定目标值f(key)的key。这可以通过collections.binarysearch(list,key,comparator)解决,其中comparator使用f(key)将值与目标键进行比较。
但是,创建和存储10
9个元素的数组需要大量的时间和内存。我想要类似collections.binarysearch()的东西,它可以对一系列自然数进行操作。我该怎么做?
请假设计算f(key)的倒数是不可行的。另外,我正在寻找一个o(logn)解决方案,其中n是密钥范围的大小。
下面是一个鼓舞人心的例子:https://www.geeksforgeeks.org/maximize-number-of-days-for-which-p-chocolates-can-be-distributed-consecutively-to-n-people/ . 我想避免自己实现二进制搜索。

zyfwsgd6

zyfwsgd61#

没有人说您需要提前创建所有元素来创建集合;)

<R> int binarySearchFunc(int range, IntFunction<? extends R> f, R key, Comparator<? super R> ord) {
    class FunctionList extends AbstractList<R> implements RandomAccess {
        @Override public int size() { return range; }
        @Override public R get(int i) {
            if(i < 0 || i >= range) throw new IndexOutOfBoundsException(i + " not in [0, " + size() + ")");
            return f.apply(i);
        }
    }
    return Collections.binarySearch(new FunctionList(), key, ord);
}

例如

// calculate sqrt(2^60) by binary search on a truncated list of perfect squares
binarySearchFunc(Integer.MAX_VALUE, i -> (long)i * i, 1152921504606846976L, Comparator.naturalOrder());
``` `ceilingKey` 以及 `higherKey` 实际上是这个函数的特例 `floorKey` 应该很容易写通过寻找“旁边”的位置指出这些。

// use a REAL optional type if you want to handle null properly
// or just use null instead of optionals if you don't
// Java's optional is just the worst of both worlds -.-
// or just use some other sentinel...
int ceilingFunc(int range, IntFunction<? extends R> f, R key, Comparator<? super R> ord) {
return -1 - binarySearchFunc(
range, i -> Optional.of(f.apply(i)), Optional.empty(),
(x, y) -> {
if(x.isPresent() && y.isPresent()) return ord.compare(x.get(), y.get());
// the "mystery element" e satisfies both e < key and x < key -> x < e
else if(x.isPresent()) return ord.compare(x.get(), key) < 0 ? -1 : 1;
else if(y.isPresent()) return ord.compare(key, y.get()) > 0 ? 1 : -1;
else return 0;
});
}
// almost the same
int higherFunc(int range, IntFunction<? extends R> f, R key, Comparator<? super R> ord) {
return -1 - binarySearchFunc(
range, i -> Optional.of(f.apply(i)), Optional.empty(),
(x, y) -> {
if(x.isPresent() && y.isPresent()) return ord.compare(x.get(), y.get());
else if(x.isPresent()) return ord.compare(x.get(), key) > 0 ? 1 : -1;
else if(y.isPresent()) return ord.compare(key, y.get()) < 0 ? -1 : 1;
else return 0;
});
}

// least i with sqrt(i) >= 10
ceilingFunc(Integer.MAX_VALUE, i -> (int)Math.sqrt(i), 10, Comparator.naturalOrder())
// least i with sqrt(i) > 10
higherFunc(Integer.MAX_VALUE, i -> (int)Math.sqrt(i), 10, Comparator.naturalOrder())

相关问题