题目
暴力解法
思路
这题最开始想到的是暴力法,用一个队列+一个数组实现。因为数据范围在1~105之间,可以用类似于桶排序的思路,插入或删除元素时在数组对应下标元素+1/-1。
复杂度分析
插入和删除的为复杂度O(1)。但是选取最大值的时候,需要从数组末端往前遍历,如果发现值大于0,则是我们要的最大值。这样,最多需要遍历105个元素,最少遍历1个。复杂度显然达不到O(1)的要求。
后来发现直接用数组滑动窗口(begin和end标记位)实现队列,需要最大值时直接遍历数组就好。真是太久没做题了Orz。
实现
class MaxQueue {
int q[20000];
int begin = 0, end = 0;
public:
MaxQueue() {
}
int max_value() {
int ans = -1;
for (int i = begin; i != end; ++i)
ans = max(ans, q[i]);
return ans;
}
void push_back(int value) {
q[end++] = value;
}
int pop_front() {
if (begin == end)
return -1;
return q[begin++];
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/solution/mian-shi-ti-59-ii-dui-lie-de-zui-da-zhi-by-leetcod/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
单调的双端队列解法
思路
当一个元素进入队列时,它前面所有比它小的元素都不会再对答案产生影响。维护一个双端队列deque,插入一个元素时,从后往前遍历,如果比待插入元素小,出队,直到遇到发现一个不小于待插入元素的元素。这样就保证了队列的单调递减。
复杂度分析
删除操作和找最大值操作显然是O(1)的,而插入操作虽然看起来有循环,做一个插入操作时最多可能会有 n 次出队操作。但要注意,由于每个数字只会出队一次,因此对于所有的 n 个数字的插入过程,对应的所有出队操作也不会大于 n 次。因此将出队的时间均摊到每个插入操作上,时间复杂度为 O(1)。
实现
class MaxQueue {
queue<int> q;
deque<int> d;
public:
MaxQueue() {
}
int max_value() {
if (d.empty())
return -1;
return d.front();
}
void push_back(int value) {
while (!d.empty() && d.back() < value) {
d.pop_back();
}
d.push_back(value);
q.push(value);
}
int pop_front() {
if (q.empty())
return -1;
int ans = q.front();
if (ans == d.front()) {
d.pop_front();
}
q.pop();
return ans;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/solution/mian-shi-ti-59-ii-dui-lie-de-zui-da-zhi-by-leetcod/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
C++复习
std::queue常用操作复习
函数签名 | 作用 |
---|---|
void std::queue::push(T) | 将元素插入队尾 |
void std::queue::pop() | 将队首元素移出队列 |
T std::queue::front() | 返回队首元素 |
T std::queue::back() | 返回队尾元素 |
std::deque常用操作复习
函数签名 | 作用 |
---|---|
void std::deque::push_front(T) | 将元素插入队头 |
void std::deque::push_back(T) | 将元素插入队尾 |
void std::deque::pop_front() | 将队首元素移出队列 |
void std::deque::pop_back() | 将队尾元素移出队列 |
T std::deque::front() | 返回队首元素 |
T std::deque::back() | 返回队尾元素 |