从每个长度为k的子阵列中找到最大值

时间:2011-02-15 17:47:01

标签: algorithm

采访问题: - 给定一个数组和一个整数k,找到每个大小为k的连续子数组的最大值。

Sample Input :

1 2 3 1 4 5 2 3 6 

3 [ value of k ]


Sample Output :
3
3
4
5
5
5
6

我无法想到比蛮力更好的东西。当数组按降序排序时,最坏的情况是O(nk)。

3 个答案:

答案 0 :(得分:2)

只需遍历数组并在self-balancing binary tree中保留k个最后元素。
向此树添加元素,删除元素并查找当前最高成本O(logk)

大多数语言为此类树提供标准实现。在STL,IIRC,它是MultiSet。在Java中,你使用TreeMap(map,因为你需要保持计数,每个元素出现多少次,而Java不提供Multi-collections)。

伪代码

for (int i = 0; i < n; ++i) {
    tree.add(a[i]);

    if (tree.size() > k) {
        tree.remove(a[i - k]);
    }

    if (tree.size() == k) {
        print(tree.max());
    }
}

答案 1 :(得分:2)

实际上你可以在O(n)时间内用O(n)空间做到这一点。

将数组拆分为每个数组。

[a1 a2 ... ak] [a(k+1) ... a2k] ...

对于每个块,再保留两个块,即左侧块和右侧块。

左侧块的第i个元素将是左侧的i个元素的最大值。 右侧块的第i个元素将是右侧的i个元素的最大值。

每个k块都有两个这样的块。

现在,如果您想要找到范围a[i... i+k]中的最大值,请说这些元素跨越上述两个k块。

[j-k+1 ... i i+1 ... j] [j+1 ... i+k ... j+k]

您需要做的就是找到第一个块i to j的RightMax和第二个块的j+1 to i+k的最大值。

答案 2 :(得分:1)

希望这是您正在寻找的解决方案:

def MaxContigousSum(lst, n):
m = [0]
if lst[0] > 0:
    m[0] = lst[0]
maxsum = m[0]
for i in range(1, n):
    if m[i - 1] + lst[i] > 0:
        m.append(m[i - 1] + lst[i])
    else:
        m.append(0)
    if m[i] > maxsum:
        maxsum = m[i]
return maxsum

lst = [-2, 11, -4, 13, -5, 2, 1, -3, 4, -2, -1, -6, -9]
print MaxContigousSum(lst, len(lst))
**Output**
20 for [11, -4, 13]