题目描述:
输入两个链表,找出它们的第一个公共节点。
如下面的两个链表:
在节点 c1 开始相交。
思路:自己没有思路,看了答案
第一个公共节点为 node ,链表 headA的节点数量为 a,链表 headB的节点数量为 b ,两链表的公共尾部的节点数量为 c ,则有:
头节点 headA 到 node 前,共有 a - c 个节点;
头节点 headB 到 node 前,共有 b - c个节点;
指针 A 先遍历完链表 headA ,再开始遍历链表 headB ,当走到 node 时,共走步数为:
a + (b - c)
指针 B 先遍历完链表 headB ,再开始遍历链表 headA ,当走到 node 时,共走步数为:
b + (a - c)
双指针问题!
双指针就是两个同时移动的指针,也可以不同时移动;
可以从同一边移动,也可以从不同的两端移动;但是需要拿到尾端的位置才能从尾端移动,一般是数组!
双指针要对移动的步数敏感!也要将两个指针移动的步数和敏感!
代码:
1)浪漫的双指针!空间复杂度 O(N+M);时间复杂度O(1);只有额外的两个指针的空间开销
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//主要问题是,节点走的顺序和快慢不同
//两个指针,将1和2分别都走一遍时,走过的路程就是一样的!
//所以在都剩下 公共区域的长度时,在到达公共点时,走过的路程长度也一样
ListNode node1 = headA;
ListNode node2 = headB;
while(node1 != node2){//判断地址
//没走到尾时,往后移,走到尾就去另一个链表中
//这里是 node1 != null 因为需要走到 null这一步,需要完成在两轮走完,都到了null,进行终止循环的判断
node1 = node1 != null ? node1.next : headB;
node2 = node2 != null ? node2.next : headA;
}
return node1;
}
}
2)哈希表;遍历第一个链表,将节点都存起来;再遍历另一个链表,比较是否包含!
时间复杂度原则上来说和 双指针一样,但是实际执行有差距
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.contains(headB)) return headB;
headB = headB.next;
}
return null;
}
}