【问题标题】:Get consecutive subarray size with largest size获取最大尺寸的连续子阵列尺寸
【发布时间】:2020-09-18 19:15:51
【问题描述】:

我有一个数字数组,现在我想找到所有连续的子数组和,其值与小于或等于 k ​​匹配。我想返回最大的子数组大小。

这是我的程序:

public static int process(List<Integer> arr, int k) {
    int size = 0;
    for (int i = 0; i < arr.size(); i++) {
        int sum = 0;
        for (int j = i; j < arr.size(); j++) {
            sum += arr.get(j);
            if (sum <= k) {
                size = Math.max(size, j - i + 1);
            }
        }
    }
    return size;
}

约束:

arr size is between 1 to 100000
array elements are between 1 to 100
k is between 1 to 1000000
    

说明:

Arrays.asList(2, 3, 5, 1, 1, 2, 1), 7

arr = 2, 3, 5, 1, 1, 2, 1

k= 7

可能的子数组:

[2], [3], [5], [1], [1], [2], [1]

[2,3], [5,1], [1,1], [1,2], [2,1]

[5,1,1], [1,1,2], [1,2,1]

[1,1,2,1]

Maximum sub array is [1,1,2,1] = its length is 4. So program should return 4.

我上周在竞争性考试中得到了这个任务,当我使用这段代码时,它只通过了 50% 的测试用例。一些隐藏的测试用例输出错误,一些测试用例超时。

我的代码有什么问题?

更新: 稍微修改了我的代码。并添加了一个示例。

【问题讨论】:

  • 你能解释一下你的问题和想要的输出吗
  • 当没有子数组添加到k时你应该返回0吗?
  • @Hades,对不起,我错过了添加它们,让我再次修改问题
  • 超时的原因是你的算法是O(n^2)。只要总和大于k,就可以通过打破内部循环来加快速度。使用滑动窗口可以大大加快速度。
  • 可能你的问题是当sum &gt; k 时你继续前进。或者,至少是其中的一部分。您应该只从i 向前看,直到那里的累积总和超过您的目标总和。

标签: java algorithm


【解决方案1】:

嵌套循环意味着性能是O(n2)。你需要重新考虑算法。

下面是一个 O(n) 解决方案,我将通过示例来展示。编写代码仍然是您的挑战。

我们需要的是一种了解特定索引之前值总和的方法。这样我们就可以计算出sumRange(i, j) = sumBefore(j) - sumBefore(i)。

由于我们正在寻找sumRange(i, j) = k,我们需要检查是否有sumBefore(i) = sumBefore(j) - k。如果我们这样做,我们就有一个候选范围为size = j - i。

因此,迭代这些值并计算累积和。构建一个 accSum 到 indexAfter 的 Map 导致该累积总和的值。

假设数组是[1, 6, 5, 3, 2, 8, 4, 2, 7, 1] 和k = 13:

Index:          0   1   2   3   4   5   6   7   8   9
Value:          1   6   5   3   2   8   4   2   7   1
accSum:     0   1   7  12  15  17  25  29  31  38  39   sumBefore
            ↓   ↓   ↓   ↓   ↓   ↓   ↓   ↓   ↓   ↓   ↓
indexAfter: 0   1   2   3   4   5   6   7   8   9  10   index

添加虚拟0 → 0 映射只是简化了代码的逻辑。

当你迭代时,你有到目前为止的累计总和,包括sumBefore(i + 1),所以看看我们是否有一个范围,即sumBefore(x) = sumBefore(i + 1) - k = accSum - k,所以在地图中查找accSum - k,如果找到,值为x,表示我们有一个候选范围x, i+1。

我希望一切都有意义。


更新

问题已更改为查找总和 &lt;= k,而不仅仅是完全等于 k 的总和。

通过将Map 更改为TreeMap,或更具体地说是NavigableMap,并将get() 调用替换为ceilingEntry() 调用,这很容易通过上述逻辑完成:

返回与给定键的大于或等于的最小键关联的键值映射,如果没有这样的键,则返回null。

如果返回的key(sum)大于参数,则结果是小于k的子数组sum。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多