题目描述
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
首先考虑的是暴力法,
就是双循环一直遍历就行:
#pragma once
#include <vector>
using namespace std;
namespace max_window
{
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
vector<int> ret;
if (num.size() < size)
return ret;
for (int i = 0; i < num.size() - size + 1; i++)
{
max = num[i];
for (int j = i; j < i + size; j++)
{
if (max < num[j])
{
max = num[j];
}
}
ret.push_back(max);
}
return ret;
}
};
}
test.cpp
#pragma once
#include "delete_repeat_list.h"
namespace delete_repeat_list
{
void start_test()
{
Solution s;
ListNode* p1 = new ListNode(1);
ListNode* p2 = new ListNode(2);
ListNode* p3 = new ListNode(3);
ListNode* p4 = new ListNode(3);
ListNode* p5 = new ListNode(4);
ListNode* p6 = new ListNode(4);
ListNode* p7 = new ListNode(5);
p1->next = p2;
p2->next = p3;
p3->next = p4;
p4->next = p5;
p5->next = p6;
p6->next = p7;
p7->next = nullptr;
auto ret = s.deleteDuplication(p1);
int c;
}
}
二、优化
暴力法肯定太捞了,不符合算法的要求,o(n)才是正道
可以采取队列在进行判断
算法如下:
维护一个序号队列,
1、新进来一个数,从队尾递减,删除比该数小的序号(这些数,在后面窗口中将不会有效,例如 队列中 8,5,2 新进数为 4,那么2这个数不在可能成为滑动窗口中最大的数,(至少的在4移除后,但4肯定在2后面移除滑动窗口)所以可以删除)
2、维护滑动窗口的有效性,从头部删除不在滑动窗口中的序号
代码如下:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
vector<int> ret;
if (num.size() < size)
return ret;
list<int> list_int;
for (int i = 0; i < num.size(); i++)
{
while (!list_int.empty() && num[i] > num[* list_int.rbegin()])
{
list_int.pop_back();
}
list_int.push_back(i);
int f = i - size;
while ((!list_int.empty()) && ((*list_int.begin()) <= (f)))
{
list_int.pop_front();
}
if (i >= size - 1)
{
ret.push_back(num[*list_int.begin()]);
}
}
return ret;
}