力扣热题100之第160题:
方法一、差值步法:
这个方法的思路为先定义两个指针,分别指向两条链表的头节点,再一人一步往后走,如果这两条链表有相交,则两个指针必定会相遇,若没有相遇则返回null,说明两条链表没有相交。
但是上述情况是在两条链表长度相等的情况下,若这两条链表不相等怎么办呢?
我们可以先找到两条链表中较长的那条,让指向长链表的那个头指针先走它们两个链表的长度差值步数,比如链表A有八个节点,长度为8,链表B有七个节点,长度为7,则它们差值步数为1,即可以先让指向链表A的头指针先走1步,然后两指针再一起往前走,若相遇则说明两条链表相交。
具体代码如下:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0; //定义链表A的长度lenA
int lenB = 0; //定义链表B的长度lenB
ListNode cur = headA; //新建一个指针cur指向链表A的头节点
ListNode ret = headB; //新建一个指针ret指向链表B的头节点
int dvalue = 0; //定义长度的差值dvalue
//求出链表A的长度
while(cur != null){
lenA++;
cur = cur.next;
}
//求出链表B的长度
while(ret != null){
lenB++;
ret = ret.next;
}
//再将两指针重新指向头节点
cur = headA;
ret = headB;
if(lenA > lenB){ //若链表A长,则cur指针先走dvalue步
dvalue = lenA - lenB;
while(dvalue != 0){
cur = cur.next;
dvalue--;
}
}else{ //若链表B长,则ret指针先走dvalue步
dvalue = lenB - lenA;
while(dvalue != 0){
ret = ret.next;
dvalue--;
}
}
//最后两指针同时往前走
while(cur != null && ret != null){
if(cur == ret){ //若此时cur和ret相遇了,则说明两条链表有相交情况,返回开始相交的节点
return cur;
}
cur = cur.next;
ret = ret.next;
}
//当while循环遍历完时还没相遇,则不存在相交
return null;
}
}
方法二、哈希集合法(HashSet):
有题目可知,若两条链表相交了,则必然在这两条链表中会有至少一个完全相同的节点,于是我们就可以先遍历一条链表A,将其所有的节点记录下来,然后遍历另一条链表B,若链表B中存在一个及以上和链表A中一样的节点,那么就说明这两条链表相交了,反之则未相交。
这里我们可以使用哈希集合来存储节点,遍历链表B的节点时,依次判断该节点是否在哈希集合中,具体代码如下:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//定义一个哈希集合set
Set<ListNode> set = new HashSet<>();
//遍历链表A,将其节点全部存入哈希集合中
while(headA != null){
set.add(headA);
headA = headA.next;
}
//遍历链表B各个节点,若该节点在集合中存在则说明相交
while(headB != null){
if(set.contains(headB)){
return headB;
}
headB = headB.next;
}
//循环遍历完说明并没有节点在集合中存在,即不相交
return null;
}
}
方法三、双指针法
若两条链表相交,则图形类似于:
因为两条链表相交,所以会有一段公共长度,如图c部分,我们创建两个指针nodeA和nodeB分别指向链表A和链表B。
让他们分别循环往前各走一步,当nodeA走完为空时,就让他前往链表B的头节点;nodeB也一样,当它走完时,让它前往A链表的头节点。之后同样继续循环往前走,因为两条链表是相交的,则nodeA和nodeB必然会相遇。
因为两条链表相交时,分为三部分:c部分是固定的,那么不管a部分和b部分谁长,走第二遍时,nodeA走过的路程为a部分长度加上b部分长度;nodeB走过的路程也为a部分长度加上b部分长度。
由此我们可以得出具体代码:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//当链表A和链表B有一条为null时,都不会相交
if (headA == null || headB == null) {
return null;
}
ListNode nodeA = headA;
ListNode nodeB = headB;
while (nodeA != nodeB) {
if(nodeA == null){
nodeA = headB;
}else{
nodeA = nodeA.next;
}
if(nodeB == null){
nodeB = headA;
}else{
nodeB = nodeB.next;
}
}
return nodeA;
}
}