📜  门| GATE-CS-2016(套装2)|问题 1(1)

📅  最后修改于: 2023-12-03 15:12:43.534000             🧑  作者: Mango

门 | GATE-CS-2016(套装2)|问题 1

这题涉及到数据结构的知识,主要考察队列的应用。

问题描述

给定一个数组和一个数k,找到数组里的数中,最大的k个数,并按照原来的相对位置返回。

例如,对于数组 [1, 23, 12, 9, 30, 2, 50] 和 k=3,返回 [23, 30, 50]

解题思路

首先我们可以用堆这种数据结构来解决这个问题,时间复杂度为 O(nlogk)。

另外一种思路是利用双端队列(deque)来解决这个问题。 我们维护一个双端队列d,这个队列中要存储数组里的下标,双端队列的头部存储的是当前最大值的下标,尾部存储的是目前为止的滑动窗口内未被淘汰的下标。

当前滑动窗口为[i, j],其中 j-i+1 = k。我们可以每次把 j 加 1,并把 i 的值加 1,这样滑动窗口就向右移动一个单位。到下一个滑动窗口 [i+1, j+1] 时,我们要比较这个滑动窗口最左边的值和队头所指的值。如果队头的值下标小于 i,那么就需要把队头出队。如果队头所指的元素小于当前的左侧元素, 则需要把队头出队。

需要注意,在队列中存储的是元素的下标而不是元素值本身,即队列中的每一项应该是类似 (index, value) 的形式。另外,如果当前数组中的元素并不是数值,而是结构体或对象之类的数据类型,需要把每一个元素的数值提取出来在队列中进行比较。

代码实现

以下是一个Python的实现代码片段,包含了两种方法。

from collections import deque
import heapq

def max_sliding_window(arr, k):
    n = len(arr)
    if n * k == 0:
        return []
    if k == 1:
        return arr

    # heap
    heap = [(-arr[i], i) for i in range(k)]
    heapq.heapify(heap)
    res = [-heap[0][0]]

    for i in range(k, n):
        heapq.heappush(heap, (-arr[i], i))
        while heap[0][1] <= i - k:
            heapq.heappop(heap)
        res.append(-heap[0][0])

    return res

def max_sliding_window_deque(arr, k):
    n = len(arr)
    if n * k == 0:
        return []
    if k == 1:
        return arr

    # deque
    q = deque()
    for i in range(k):
        while q and arr[i] >= arr[q[-1]]:
            q.pop()
        q.append(i)

    res = [arr[q[0]]]

    for i in range(k, n):
        if q[0] == i - k:
            q.popleft()
        while q and arr[i] >= arr[q[-1]]:
            q.pop()
        q.append(i)
        res.append(arr[q[0]])

    return res

以上是使用两种不同的解法来解决本题的代码实现。堆的效率需要更高,但需要使用额外的空间作为堆的辅助空间。使用双端队列可以避免使用额外的空间,但是需要更多的代码来实现。

最好的做法应该是遍历数组时,把最大值保存在变量中,同时记录下它所处的位置。再利用一个集合(set)来记录内部最大值的数量,如果当前数字比最大值还大,那么就把全部集合清空并记录值和位置。这种做法的时间复杂度为$O(n)$,空间复杂度为$O(k)$。

##参考链接

[1] https://leetcode.com/problems/sliding-window-maximum/

[2] https://leetcode.com/articles/sliding-window-maximum/

[3] https://www.geeksforgeeks.org/sliding-window-maximum-maximum-of-all-subarrays-of-size-k/

[4] https://blog.csdn.net/huanghanqian/article/details/88938612