给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。
例如,
给定 nums = [1,3,-1,-3,5,3,6,7],和 k = 3 。
窗口位置 最大值
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
由此可见,返回最大的滑动窗口为:[3,3,5,5,6,7]。
注意:
你可以假设 k 一直都是有效的,例如:1 ≤ k ≤ 输入数组的大小,输入数组不为空。
进阶:
你能在线性时间复杂度内解决此题吗?
from collections import deque
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
# deque为双端队列
dq = deque()
max_numbers = []
# 方法四:使用双向队列,时间复杂度O(n)。
# 在队列中维持一个k长度窗口内的递减元素下标,为什么呢?因为当元素递增时,前面的元素就不需要了,因为最大值肯定不会是它们了。
#
# 顺序扫描每一个元素,当队头的元素超出窗口视野的时候,将对头元素出队;然后检查队尾,如果队尾元素小于或等于当前元素,
# 则队尾元素出队,重复检查队尾直至队列为空或者队尾元素大于当前元素。然后当前元素入队。
# 顺序扫描每一个元素
for i in range(len(nums)):
# 当队列中有值,并且元素递增时,让之前的元素出对
# 之所以要判断dq不为空,是因为第二个条件需要取出对应的值进行比较
while dq and nums[i] >= nums[dq[-1]]:
dq.pop()
# 将当前的元素入队
dq.append(i)
# 如果当前的i已经大于滑动窗口的大小,并且dq中的长度已经大于k,最先入队的下标和当前的下标之间的差值-1,一定是小于等于K。
if i >= k and dq and dq[0] == i - k:
# 出头元素
dq.popleft()
# 窗口滑动
if i >= k - 1:
# 取出最大值
max_numbers.append(nums[dq[0]])
return max_numbers
if __name__ == "__main__":
nums = [3, 1, -1, -3, 5, 3, 6, 7]
print(Solution().maxSlidingWindow(nums,3))
cpp代码
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq;
vector<int> max_numbers;
for (int i = 0; i < nums.size(); ++i) {
while (!dq.empty() && nums[i] >= nums[dq.back()]) {
dq.pop_back();
}
dq.emplace_back(i);
if (i >= k && !dq.empty() && dq.front() == i - k) {
dq.pop_front();
}
if (i >= k - 1) {
max_numbers.emplace_back(nums[dq.front()]);
}
}
return max_numbers;
}
};
网友评论