算法复习-数组
数组双指针——左右指针
双指针操作时候left=0,right=s.size()-1,注意指针越界问题,判断时候有短路问题,先验边界!
两端向中间
n数之和
有序数组的平方
-4 0 12 15 按平方大小重排
思路:两个指针分别指向数组的两端,比较两端元素的平方大小,将较大的平方放到结果数组的末尾,并移动对应的指针,直到两个指针相遇。
回文串相关
中间向两端(最长回文子串)
遍历每一个“中心”向外扩散(从一个中心扩散或者两个中心扩散)
1 | for 0 <= i < len(s): |
二分查找
数组有序就考虑
找一个元素
左闭右开区间[left, right)
- while(left < right) 因为当left == right时,区间已经没有元素了,可以跳出
- left = mid + 1; left所指的元素还要再找,所以指向跳过mid这个元素的位置
- right = mid; right所指向的mid刚好不用再找
1 | int binarySearch(vector<int>& nums, int target){ |
颜色分类(荷兰国旗问题)
三指针,分别指向0的右边界、当前元素、2的左边界,遍历数组
如果是 0:与 nums[low] 交换,low++、mid++(新交换进来的元素已处理为 0 或 1)。
如果是 1:mid++(跳过)。
如果是 2:与 nums[high] 交换,high–(交换进来的元素必须再次检查,因此不移动 mid)。
1 | void sortColors(vector<int>& nums) { |
数组双指针——快慢指针
去重/删除/移动元素
一个慢指针用来写,一个快指针用来在前面扫
1 | int slow = 0, fast = 0; |
滑动窗口(重点)
同样用左闭右开区间。slow fast指针不回退,所以只用O(n)扫一遍数组,O(n2)全遍历的部分情况不用扫
外循环更新right,内循环更新left,[left,right)左闭右开区间
求最长:不断加入right,while(窗口不合法)时才收缩,收缩到符合条件出while循环,更新答案,因为此时窗口刚刚恢复合法。
1 | for (int right = 0; right < n; ) { |
求最短:不断加入right,while(窗口合法)时收缩left,尝试找到更短的答案,收缩到不合法出while循环,在while内更新答案,因为while内部窗口是合法的。
1 | for (int right = 0; right < n; ) { |
通用外层框架
1 | // 滑动窗口算法框架伪码 |
- 最小覆盖子串
维护need,window两个unordered_map哈希表,字符移入移出时更新window,当某个字符是need所需且符合/不符合数量时更新valid,valid == need.size()时说明窗口已经覆盖了need,进入内循环更新结果并缩小窗口1
2unordered_map<char, int> need, window;
if(need.count(c)) // 判断c是否在need中
小巧思
n*n二维方阵原地旋转
先主对角线翻转,再水平翻转
螺旋矩阵
待补充
合并两个有序数组
从后往前扫填补就可以
将矩阵按对角线排序(未完成)
在同一个对角线上的元素,其横纵坐标之差是相同的。有了这个规律辅助,这道题就很容易做了,我直接用一个哈希表把每个对角线的元素存起来,想办法排序,最后放回二维矩阵上即可。
二维网格迁移
二维数组按一维数组往后走k步,后k个到前面。先把二维数组映射为一维的下标,然后处理一维(三次reverse)

