常用思路技巧
双指针
很多线性的数据结构比如数组、链表、字符串(看做char数组),都会经常用到双指针的思路。也可以叫双索引、双下标等等,而且也不一定只有两个指针。总之核心思想就是用多个变量、来保存感兴趣的信息。
一些常见的思路比如:
-
用于指导结果存放的指针,可能是一个特定位置,也可以是多个限定某个区间等等
-
标记一个特定的窗口、子序列、子数组等等
-
从某个特定位置分别往上下界进行迭代的指针
双指针的循环写法上,一般也就两类。前者需要在循环外做好非空处理,后者则需要注意在循环内判断。具体要看哪种方式编码更为简洁了。
while(a!=null && b!= null)
while(a!=null || b!= null)
纯下标计算类
一般是多维数组相关的题目,比如:
- 多维向一维展开
- 多维数组行or列优先遍历
- 二维数组的各种对称、翻转等等
辅助数据结构
通过HashMap HashSet进行去重、存储元素下标信息、存储元素出现次数、存储元素是否曾经出现等。
除了引入其他数据结构,有时候限制空间复杂度O(1),这时候要考虑到数组本身在某些操作后,是否可以用来辅助记录信息,以及在最后是否需要清除恢复。
对于字符串类也会经常用到的技巧:
- 如果是只有小写字母,可以开一个int[26]来实现HashMap的作用。下标为 char - 'a
- 如果是ASCII码,一般也就是数字+大小写+特殊字符,此时要开 int[256]的,下标直接用int将字符强转就行了
- 当然也可以用HashMap,其实性能和存储空间并不会差太多。
区间类问题
两大核心思路:
- 一定要先画图,各种区间的相交、合并等情况,画图穷举,方便理解
- 排序,根据实际情况,将起点或者重点排序,结合自己的画图理解思考如何设计代码的编写
滑动窗口
其实是双指针的一种,也是比较有套路的一类题目
常见的解题思路模版如下:
下面第1和第2步一般都是相反的操作,比如1是加上nums[right] 那么2很多都是 减去 nums[left]
while(right 遍历从0到N) {
计算当前窗口的信息windowRet // 1 比如乘积、和等
while(满足要求 && left <= right) { //left <= right 保证至少有一个元素在窗口中
//收集满足要求的结果(optional)
去掉left位置的信息,windowRet - left // 2
left++
}
//收集不满足要求的结果(optional)
}