diff --git a/include/s0239_sliding_window_maximum.hpp b/include/s0239_sliding_window_maximum.hpp new file mode 100644 index 0000000..b1523e8 --- /dev/null +++ b/include/s0239_sliding_window_maximum.hpp @@ -0,0 +1,15 @@ +#ifndef S0239_SLIDING_WINDOW_MAXIMUM_HPP +#define S0239_SLIDING_WINDOW_MAXIMUM_HPP + +#include +#include +#include + +using namespace std; + +class S0239 { + public: + vector maxSlidingWindow(vector& nums, int k); +}; + +#endif diff --git a/notes/src/SUMMARY.md b/notes/src/SUMMARY.md index f86fc7c..4e12bb0 100644 --- a/notes/src/SUMMARY.md +++ b/notes/src/SUMMARY.md @@ -29,6 +29,7 @@ # 栈与队列 +- [总结](./stack_and_queue.md) - [用栈实现队列 && 用队列实现栈](./impl_stack_queue.md) # 经典代码 diff --git a/notes/src/stack_and_queue.md b/notes/src/stack_and_queue.md new file mode 100644 index 0000000..58ef3ff --- /dev/null +++ b/notes/src/stack_and_queue.md @@ -0,0 +1,70 @@ +# 总结 + +## 栈 + +使用场景: + +1. 需要先进后出的数据结构 +2. 匹配问题 + +经典题目: + +[20. 有效的括号](https://leetcode.cn/problems/valid-parentheses/) + +[1047. 删除字符串中的所有相邻重复项](https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/) + +## 队列 + +使用场景: + +1. 先进先出的数据结构 +2. 滑动窗口 + +### 变体:优先级队列 + +队列中的数据以 `` 的形式存储,每一个 `value` 都有一个 `priority` 。 + +当入队,我们根据 `priority` 将元素插入到队列的相应位置,队列中的元素总是按优先级升序或者降序排列。 + +```cpp +#include +#include +#include +#include + +int main(int argc, const char *argv[]) { + // priority 为 int 类型,value 为 std::string 类型 + std::priority_queue> q; + // 写入元素 + q.push(std::make_pair(3, "Microsoft")); + q.push(std::make_pair(1, "Surface")); + q.push(std::make_pair(2, "Apple")); + q.push(std::make_pair(4, "MacBook")); + // 访问顶部元素 + std::cout << q.top().first << q.top().second << std::endl; + // 删除顶部元素 + q.pop(); + // 检查是否为空 + if (q.empty()) { + std::cout << "Empty" << std::endl; + } else { + std::cout << "Not empty" << std::endl; + } + return 0; +} +``` + +输出: + +```text +4MacBook +Not empty +``` + +优先队列用一般用堆来实现,具有 `O(log n)` 时间复杂度的插入元素性能,`O(n)` 的初始化构造的时间复杂度。 + +经典题目:[239. 滑动窗口最大值](https://leetcode.cn/problems/sliding-window-maximum/) + +### 变体:单调队列 + +经典题目:[239. 滑动窗口最大值](https://leetcode.cn/problems/sliding-window-maximum/) diff --git a/src/s0239_sliding_window_maximum.cpp b/src/s0239_sliding_window_maximum.cpp new file mode 100644 index 0000000..78312e1 --- /dev/null +++ b/src/s0239_sliding_window_maximum.cpp @@ -0,0 +1,36 @@ +#include "s0239_sliding_window_maximum.hpp" +#include + +// 优先级队列实现,每次操作的时间复杂度是 O(log(n)) ,因此总的时间复杂度是 O(n*log(n)) +// 空间复杂度是 O(n) +vector S0239::maxSlidingWindow(vector& nums, int k) { + int len = nums.size(); + if (len < 1 || k < 1) { + return {}; + } + vector result; + // 初始化优先级队列 + priority_queue> q; + for (int i{0}; i < len && i < k; ++i) { + q.push(make_pair(nums[i], i)); + } + if (k >= len) { + return {q.top().first}; + } else { + result.push_back(q.top().first); + } + // 开始迭代 + for (int i{1}; i + k - 1 < len; ++i) { + // 本轮迭代中滑动窗口的范围是 [i...i+k-1] + // 先把右边的元素放入队列 + q.push(make_pair(nums[i + k - 1], i + k - 1)); + // 确保队首元素在滑动窗口内 + // 如果不在滑动窗口内,则弹出 + while (q.top().second < i) { + q.pop(); + } + // 现在队首元素就是滑动窗口内的最大值了 + result.push_back(q.top().first); + } + return result; +} diff --git a/tests/s0239_sliding_window_maximum.cpp b/tests/s0239_sliding_window_maximum.cpp new file mode 100644 index 0000000..5ab7557 --- /dev/null +++ b/tests/s0239_sliding_window_maximum.cpp @@ -0,0 +1,19 @@ +#include "s0239_sliding_window_maximum.hpp" + +#include + +TEST(Problem239, Case1) { + vector nums{1, 3, -1, -3, 5, 3, 6, 7}; + int k{3}; + vector expected{3, 3, 5, 5, 6, 7}; + S0239 solution; + EXPECT_EQ(solution.maxSlidingWindow(nums, k), expected); +} + +TEST(Problem239, Case2) { + vector nums{1}; + int k{1}; + vector expected{1}; + S0239 solution; + EXPECT_EQ(solution.maxSlidingWindow(nums, k), expected); +}