【问题标题】:Efficient algorithm for finding largest index j such that sum from index i to j is less than k查找最大索引 j 的有效算法,使得从索引 i 到 j 的总和小于 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 请查看正确答案
  • 很好!..从技术上讲,以前的答案并不正确,所以也许可以更改第一行?

标签: arrays algorithm


【解决方案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 树(扩展了前缀求和的想法)linklink
猜你喜欢
  • 2014-11-25
  • 2013-08-19
  • 1970-01-01
  • 2020-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
相关资源
最近更新 更多