在非负1D数组 x
中,我们希望找到最短的切片,以便 x [start:end] end] .sum()>阈值
,带有可选约束, start< = argmax(x)<结束
。必须与浮子和整数一起工作。
是否有已知的算法可以实现这一目标?我已经实施了一个在这里,但它不如我希望,理想情况下应该没有重量级依赖性(例如NUMBA)。示例:
x = [0, 1, 2, 3, 4, 9, 7, 1, 0, 0, 0]
threshold = 3 + 4 + 9 + 7 - .01
start, end = func(x, threshold)
print(x[start:end])
[3 4 9 7]
@גלעדגלעד的答案在numba中可以接受。 , for 等 - 除非某人可以指向轻量级的numba ...
In a non-negative 1D array x
, we wish to find the shortest slice such that x[start:end].sum() > threshold
, with the optional constraint that start <= argmax(x) < end
. Must work with floats and integers.
Is there a known algorithm to accomplish this? I have implemented one here, but it's not as fast as I wish, and ideally there shouldn't be a heavyweight dependency (e.g. numba). Example:
x = [0, 1, 2, 3, 4, 9, 7, 1, 0, 0, 0]
threshold = 3 + 4 + 9 + 7 - .01
start, end = func(x, threshold)
print(x[start:end])
[3 4 9 7]
@גלעד ברקן's answer is acceptably fast in numba; my implem. Though, non-numba is strongly preferred, meaning minimizing if
, for
, etc - unless someone can point to a lightweight numba...
发布评论
评论(3)
这让我想起了找到包括集合的所有成员的最小窗口的问题,该窗口可以在O(n)时间和O(k)空间中使用两个指针来解决。在我们的情况下,o(1)空间似乎足够了,因为我们只对一笔款项感兴趣。
移动正确的指针,直到达到总和为止。移动左指针,直到总和再次太低为止。然后移动正确的指针等。解决读者留给读者的gragmax约束。
This reminds me of the problem of finding the smallest window that includes all members of a set, which can be solved in O(n) time and O(k) space with two pointers. In our case, O(1) space would seem to be enough since we're only interested in a sum.
Move the right pointer until the sum is achieved. Move the left pointer just until the sum is again too low. Then move the right pointer, etc. Addressing the argmax constraint left to the reader.
只是我的几美分:
,因为数组是非负的,所以每个索引中包含运行总和的列表已经是一个排序的列表。
在每个索引上计算运行总和,并构建一个元组列表(runned_sum,current_index)。
如果索引的运行总和超过了阈值的外观,则在运行总和列表中的最大值(runned_sum -sum -threshold)的最大值外观,使用二进制搜索在当前索引处不包括一个在当前索引处的值
现在,当前范围是[index_found_found_by_binary_binary_search_search +1,curr_index]
在所有此类范围内最小化。
在您的示例中:
运行总和为:
[0,1,3,6,10,19,26,27,27,27,27,27]
总和(26)超过索引的阈值
22.99在阈值和总和之间为26-22.99 = 3.01。
查找小于 3.01的最大值 - 这可以通过二进制搜索来完成。
我们需要最大的价值,因为我们想最大程度地减少范围。
小于3.01的
3
最大的值是 范围。
不确定这是否是您已经做的。
Just my few cents:
Because the array is non-negative the list containing running sum at each index is already a sorted list.
Compute running sum at each index and construct a list of tuples (running_sum, current_index).
If the running sum at an index exceeds the threshold look for the greatest value that is less than (running_sum - threshold) in the list of running sums excluding the one at current index using binary search
Now the current range is the [index_found_by_binary_search+1, curr_index]
Minimize upon all such ranges.
In your example:
the running sum is:
[0, 1, 3, 6, 10, 19, 26, 27, 27, 27, 27]
The sum(26) exceeds threshold of 22.99 at index = 6
Now difference between threshold and sum is 26 - 22.99 = 3.01.
Look for the greatest value that is smaller than 3.01 - this can be done by binary search.
We need greatest value because we want to minimize the range.
The greatest value is 3 that is smaller than 3.01 and can be found at index 2.
The result is the range [2+1, 6] = [3,6]
Now do this all along the array and minimize upon the length of the range.
Not sure if that is what you already did.
感谢 @גלעדגלעד的指示。 numba/plain Python是在这里 >),具有贪婪的验证,以及下面的Cython( numpy tutorial )代码> float64 ,对于
float32
的速度更快10%当len(x)= 1E6
时。它们比我可能想出的最快的numpy vectorized Impem快X10。注意,对于
float32
和长序列,它具有圆形不精确的折磨,而应将总和计算为(尽管较慢):argmax
约束可以通过边界来满足约束左
和右
适当地,当然,一旦知道正确的间隔,我们就可以轻松获取确切的索引。与Numba不同,Cython的轻量级保留了Python的语法减去键入(至少对于我的情况)。Thanks to @גלעד ברקן for the pointers. Numba/plain Python is here (just add
@jit
), with greedy validation, and below's Cython (numpy tutorial), which equals Numba's speed onfloat64
and is 10% faster forfloat32
whenlen(x)=1e6
. They're x10 faster than the fastest numpy-vectorized implem I could come up with.Note, for
float32
and long sequences, it suffers from roundoff imprecision, and instead one should compute the sum as (though it's slower):The
argmax
constraint is easily satisfied by boundingleft
andright
appropriately, and of course we can fetch the exact indices easily once we know the right interval. Unlike Numba, Cython's lightweight while retaining Python's syntax minus typing (at least for my case).