查找最大索引 j 的有效算法,使得从索引 i 到 j 的总和小于 k
Posted
技术标签:
【中文标题】查找最大索引 j 的有效算法,使得从索引 i 到 j 的总和小于 k【英文标题】:Efficient algorithm for finding largest index j such that sum from index i to j is less than k 【发布时间】:2021-02-17 15:51:54 【问题描述】:我得到一个大小为 n 的正整数数组。对于数组的每个索引 i,我想找到最大的索引 j,使得从索引 i 到 j 的数组元素之和小于或等于某个整数 K。我只能想到蛮力 O (n^2) 方式。我想知道是否有更有效的方法?
【问题讨论】:
我想到了对范围 i 到 n-1 的二进制搜索,假设数组已排序。我相信这会给你 nlog(n)。 啊,是的,正如@Andrew Vershinin 所指出的,我们需要找到前缀总和,然后进行二分搜索得到 O(nlgn)。 @gateway2745 请查看正确答案 很好!..从技术上讲,以前的答案并不正确,所以也许可以更改第一行? 【参考方案1】:之前的答案不正确,但我会留下它,因为它已被接受并有评论。
有一个O(n)
时间,O(1)
空间滑动窗口(或,“两个指针”)的方法。下面的代码是Java:
public static int[] rightBoundSums(int[] arr, long K)
final int N = arr.length;
int[] ans = new int[N]; // the result
int r = 0; // the right index of the window
long sum = 0; // current sum
for (int l = 0; l < N; l++)
// invariant: r is the first such index that
// sum(l, r - 1) > K, or N, if the end of the array was reached
while (r < N && sum <= K)
sum += arr[r++];
if (arr[l] > K)
ans[l] = -1; // if the i-th element itself is larger, than K, there is no such j
else
ans[l] = (r == N) ? N - 1 : r - 2;
sum -= arr[l];
return ans;
计算前缀和pref[0] = 0, pref[i] = pref[i - 1] + arr[i - 1]
。总和将单调递增,因为 arr
的值为正数,因此您可以对每个 i
的前缀总和 pref[i + 1] ... pref[N]
使用二分搜索值 arr[i] + k
(请注意前缀总和是 1 索引的事实) .由此产生的复杂性将是O(N logN)
时间和O(N)
空间。
【讨论】:
赞成这个答案。此外,如果需要数组来允许更新,则可以使用 Fenwick 树(扩展了前缀求和的想法)link; link以上是关于查找最大索引 j 的有效算法,使得从索引 i 到 j 的总和小于 k的主要内容,如果未能解决你的问题,请参考以下文章