本文试图总结滑动窗口与双指针的思想。因为二者实在太过类似,因此放在了同一篇总结文章中。
1. 常用双指针思想
双指针是解数组、链表题中最常见的思想之一。总的来说有四大用途:
- 快慢指针:一个指针移动两步,一个指针移动一步。或者两指针移动起点相差K。
- 头尾指针:指针一头一尾同时向内靠近。最常见的就是翻转字符串。
- 栅栏指针:两个指针仿佛围成一个栅栏,一个指针的一侧全部存放符合要求的节点,另一个指针负责遍历寻找。常用于要求原地处理的题目。
- 滑动窗口:两个指针一前一后形成一个窗口,不满足条件时前面的不停扩大窗口,满足时后面指针前进,缩小窗口,由可行解寻找最优解。
当然这个分类很主观,种类间也有思想重叠。
2. 快慢指针
Leetcode - 19.删除链表的倒数第N个节点 、Leetcode - 142.环形链表II
总的来说快慢指针就是为了利用数学性质完成在链表中的定位,在链表中很有效的原因就是因为链表不能通过下标取元素。
2. 头尾指针
Leetcode - 151 反转字符串中的单词、Leetcode - 344 反转字符串、Leetcode - 541 反转字符串Ⅱ
翻转题往往会有先整体翻转一次,再局部翻转一次的trick。
while(right >= left) {
char temp = s[left];
s[left] = s[right];
s[right] = temp;
right --;
left ++;
}
3. 栅栏指针
Leetcode - 27 移除元素
栅栏指针也是常用的思想,它往往在要求原地处理的题目中work。快排中也应用到了该思想。需要注意的是,两指针不能发生冲突,即形成栅栏的指针与负责移动的指针之间要足够泾渭分明。
4.滑动窗口
Leetcode - 206 长度最小的子数组
滑动窗口的问题往往不同窗口之间存在公共前缀或者后缀的关系,为了避免重复运算,才会进行滑动窗口进行优化。