移除元素
此题做法在数组章节中。
反转字符串
此题做法在字符串章节中。
替换数字
此题做法在字符串章节中。
翻转字符串里的单词
此题做法在字符串章节中。
翻转链表
此题做法在链表章节中。
删除链表的倒数第N个节点
此题做法在链表章节中。
链表相交
此题做法在链表章节中。
环形链表II
此题做法在链表章节中。
三数之和
此题做法在哈希表章节中。
四数之和
此题做法在哈希表章节中。
总结
数组篇
原地移除数组上的元素,不能真正的删除,只能覆盖。
一些同学可能会写出如下代码(伪代码):
for (int i = 0; i < array.size(); i++) {
if (array[i] == target) {
array.erase(i);
}
}
这个代码看上去好像是O(n)的时间复杂度,其实是O(n^2)的时间复杂度,因为erase操作也是O(n)的操作。
所以此时使用双指针法才展现出效率的优势:通过两个指针在一个for循环下完成两个for循环的工作。
字符串篇
反转字符串,注意这里强调要原地反转,要不然就失去了题目的意义。
使用双指针法,定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素,时间复杂度是O(n)。
在替换数字中介绍使用双指针填充字符串的方法,如果想把这道题目做到极致,就不要用额外的辅助空间。
思路就是首先扩充数组到每个数字替换成number之后的大小。然后双指针从后向前替换数字。
其实很多数组(字符串)填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
在删除冗余空格的过程中,如果不注意代码效率,很容易写成了O(n^2)的时间复杂度。其实使用双指针法O(n)就可以搞定。
主要还是erase用的比较随意,一定要注意for循环下用erase的情况,一般可以用双指针写效率更高。
链表篇
使用双指针法来翻转链表,只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表。
在链表中求环,应该是双指针在链表里最经典的应用。
使用快慢指针(双指针法),分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。
找到环的入口,其实需要点简单的数学推理。
N数之和篇
去重的过程不好处理,有很多小细节,如果在面试中很难想到位。
通过前后两个指针不算向中间逼近,在一个for循环下完成两个for循环的工作。
对于三数之和使用双指针法就是将原本暴力O(n3)的解法,降为O(n2)的解法,四数之和的双指针解法就是将原本暴力O(n4)的解法,降为O(n3)的解法。
同样的道理,五数之和,n数之和都是在这个基础上累加。