个人总结,可以考虑用双指针的地方
1.链式结构
2.可以通过一个指针遍历整个表,存入扩展存储空间中,然后再依次取出或者取出某特定的一个
比如返回链表的倒数第k个节点,可以让一个指针先走k步,然后两个指针一起走,前面的指针到尽头之后,后面的指针停在倒数第k个上
3.存在两个节点之间比较的情况
4.涉及有序链表,迭代
比如把两个有序排列的链表合并成一个有序的,或者把一个有序链表或者顺序表按某种规则拆成两部分
分类很多,比如两个链表平行指针,在一个链表同步移动但一前一后的指针,一个负责遍历一个负责指示当前操作位置的双指针,两个指针分别位于两端向中间移动直到相遇的碰撞指针,还有两个指针同时移动但每次移动步数不同的快慢指针
有些题目可以用多种方式,比如快速排序可以左右两个指针向中间移动直到碰撞,可以一个指针去遍历整个表寻找小于基准的数,另一个指针指向下一个小于基准的数应该存放的位置
同时移动但移动步数不同的快慢指针,我目前只了解到找链表环路这一个用法
输入两个链表,找出它们的第一个公共节点。
找公共节点这个题,挺难想到的,一般方法都是要额外存储,或者时间复杂度很高
1、最暴力的查找就不提了
2、遍历链表a并用HashSet存储,遍历链表b并依次尝试存入,如果.add()返回值为false,说明这个值已经在表中,直接将其返回,程序结束
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> set = new HashSet<>();
while(headA != null){
set.add(headA);
headA = headA.next;
}
while(headB != null){
if( set.add(headB)== false) return headB;
headB = headB.next;
}
return null;
}
}
3.反向思考,不是找第一个相同的节点,而是找第一个不相同的节点
两个链表合一之后,后面就只有一个链了,遍历链表A和B,分别把每个节点都存入Stack中,然后倒着pop()出来并且比较,直到某一次pop(),A和B的节点不相同,在这的前一个,就是所要的节点
4、双指针,不知道什么样的脑袋才想得出来这种解法,我人都看傻了
为了写起来省事,用小写a和b表示A和B的长度,c表示A和B合并后剩下的长度
所以用一个指针遍历链表a,总长a+c,用一个指针遍历链表b,总长b+c
那么,如果让一个指针遍历A结束后转去指向B的head节点,遍历链表到结束
同时,另一个指针从B开始遍历,到尽头后转到A,再次遍历链表到结束
在这个过程中,指针会路过两次我们要找的【第一个相同节点】,找这两个时分别走了多少路呢?
A链表:第一次:a,第二次:a+c+b
B链表:第一次:b,第二次:b+c+a
也就是说,两个指针同步向后移动的话
如果A和B有交点,会在走了a+b+c的路程之后同时位于那个交点的位置
如果A和B没有交点,两个指针都会走a+b+2c的总路程,然后同时指向null
那么代码的逻辑是这样的:
1.如果A和B任一为空,直接返回null
2.A和B均不为空,进入循环,建立两个指针a和b
2.1 循环跳出条件是两个指针相等,a=b,这个节点就是要找的
2.2 a和b同时向后移动一位,即指向它的next节点
2.3 如果a和b同时为空,说明这两个链表没有交点,返回null
2.4 如果a和b有一个为空,那么将其指向另一个链表的head
我这个是循环外面不用写return的,符合条件都是循环内直接return,有些地方可能会报错。。。或者进入无限循环超时,还死活找不到哪里出错。。。
如果你笔试的系统不是很靠谱,还是老老实实最后再return比较好
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) return null;
ListNode a = headA;
ListNode b = headB;
while(true){
if(a == b) return a;
a = a.next;
b = b.next;
if(a == null && b == null )return null;
if(a == null){
a = headB;
}
if(b == null){
b = headA;
}
}
//return null;
}
}