【Day2】数组Part2
209. 长度最小的子数组
-
思路:
落实到代码中时,要分两部分实现:右指针不断前进,它每前进一步后、又要等待左指针是否要追过来。具体的:
- 当窗口不再符合要求时,右指针才继续前进。
- 当窗口符合了要求之后,右指针就要开始追过来,直到窗口不再符合要求。
注意:(几点概括)
滑动窗口的核心思想是:寻找符合题目要求的最大窗口(亦即——最长子串)。
具体来说:
- 前提:保持扩展/收缩方向一致、不变;
- 重点:讲题目中的描述种种要求总结为 ——
要什么样的最长子串
,条件才是中心需求 - 注意:什么时候进行子串的记录?—— 在子串符合题目要求的时候进行记录。
-
代码:
class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int l = 0; int smallest = nums.size() + 1; int sum = 0; // 窗口前进 for (int r = 0; r < nums.size(); r++) { sum += nums[r]; while (sum >= target) { // 先记录再行动 int len = r - l + 1; if (smallest > len) { smallest = len; } sum -= nums[l++]; // 窗口缩减 } cout << l << " " << r << " " << sum << endl; } return smallest == nums.size() + 1 ? 0 : smallest; } };
-
练习:
class Solution { public: int totalFruit(vector<int>& fruits) { int len = fruits.size(); int l = 0; unordered_map<int, int> types; int max_len = 0; for (int r = 0; r < len; r++) { int type_r = fruits[r]; if (types.count(type_r)) { types[type_r]++; } else { types[type_r] = 1; } // 当种类多于2个,开始收缩窗口 while (types.size() > 2 && l < len) { int type_l = fruits[l++]; if (types[type_l]) { types[type_l]--; if (types[type_l] == 0) { types.erase(type_l); } } } if (types.size() <= 2) { int sum = r - l + 1; max_len = sum > max_len ? sum : max_len; } } return max_len; } };
54. 螺旋矩阵
-
思路:
可以通过"指南针"方法(存储不同方向的坐标变化量,循环中只需要根据不同条件进行方向变化即可)进行模拟行走路线、避免过于繁杂的判断和计算。
- 注意对已访问元素的标记,可以用
vector<vector<bool>>
数组进行记录,性价比较高。
- 注意对已访问元素的标记,可以用
-
代码:
class Solution { private: pair<int, int> directions[4] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; public: vector<int> spiralOrder(vector<vector<int>>& matrix) { if (matrix.empty() || matrix[0].empty()) return {}; // 处理空矩阵 int len_r = matrix.size(); int len_c = matrix[0].size(); vector<vector<bool>> visited( len_r, vector<bool>(len_c, false)); // 标记已访问的单元格 int i = 0, j = 0; int cur_der = 0; vector<int> result; while (result.size() < len_r * len_c) { result.push_back(matrix[i][j]); visited[i][j] = true; // 标记当前单元格为已访问 cout << matrix[i][j] << " "; // 要碰到边界or新的一步已访问过 ——> 切换方向 int next_i = i + directions[cur_der].first; int next_j = j + directions[cur_der].second; if (next_i < 0 || next_i >= len_r || next_j < 0 || next_j >= len_c || visited[next_i][next_j]) { cur_der = (cur_der + 1) % 4; } // 更新当前位置 i += directions[cur_der].first; j += directions[cur_der].second; } return result; } };