一、双指针法
(一)概况
1.类型:快慢指针(相同方向循环)、对撞指针(相反方向循环)、滑动窗口
2.用途:提高效率,通常能将将O(n^2)的时间复杂度,降为O(n)
3.可应用的数据结构:数组、链表、字符串等
4.应用场景:
需要用到遍历、循环、双层for循环时,立马想到双指针法
普通双指针:反转链表、链表中的虚拟头结点法(这里归类可能不恰当)
快慢指针:删除重复元素或倒数第n个节点、判断链表是否有环、N数之和、
对撞指针:二分查找、翻转字符串等
滑动窗口:在数组或者链表某个连续的区间上的操作,比如求最长/最短子字符串、长度最小子数组
(二)相关题目
1.普通双指针法:
206. 反转链表
反转链表题目要求:
思路:设置一个节点pre,新建一个节点cur=头结点,令cur始终指向pre从而完成反转
代码:
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode pre = null;
ListNode temp = null;
while(cur != null){
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
2.快慢指针:
27. 移除元素
面试题 02.07. 链表相交
142. 环形链表 II
19. 删除链表的倒数第 N 个结点
删除链表的倒数第N个节点题目要求:
思路:未知链表长度,先利用一个指针fast走N步,再利用fast!=null,找到被删节点的前驱
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode fast = head;
ListNode slow = dummy;
for (int i = 0; i < n; i++) {
fast = fast.next;
}
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
// 注意slow的原始指针为dummy,所以需要多next一步
slow.next = slow.next.next;
return dummy.next;
}
3.对撞指针
151. 反转字符串中的单词
541. 反转字符串 II
344. 反转字符串
反转字符串的题目要求:
思路:对撞双指针法
public void reverseString(char[] s) {
int l = 0;
int r = s.length - 1;
while (l < r){
s[l] ^= s[r];
s[r] ^= s[l];
s[l] ^= s[r];
r--;
l++;
}
}
4.滑动窗口
209. 长度最小的子数组
904. 水果成篮
具体见博客https://blog.csdn.net/xiaomingming99/article/details/128648488?spm=1001.2014.3001.5502