给定两个单链表的头节点headA和headB, 请找出并返回两个单链表相交的起始节点. 如果两个链表没有交点, 返回null.
图示两个链表在节点c1开始相交, 题目数据保证整个链式结构中不存在环.
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
示例 2:
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
提示:
- listA 中节点数目为 m
- listB 中节点数目为 n
- 0 <= m, n <= 3 * 104
- 1 <= Node.val <= 105
- 0 <= skipA <= m
- 0 <= skipB <= n
- 如果 listA 和 listB 没有交点,intersectVal 为 0
- 如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]
思路
这道题首先想到的是将链表A的每个节点存入Set, 再使用链表B去挨个比对, 若比对成功返回, 否则返回null即可.
第二想到的方法是使两个链表的临时指针在同一位置上, 同时前进, 比对指向的值是否一致.
在看到Leetcode题解后发现还有第三种方法, 双指针法. 首先在链表A和B处各定义一个临时指针, 同时向前遍历, 若指针为空则指向另一条链表继续遍历, 当两指针指向同一节点时返回目标节点, 或返回null.
代码实现
HashSet:
/**
* 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) {
Set<ListNode> set = new HashSet<ListNode>();
ListNode temp = headA;
while(temp != null) {
set.add(temp);
temp = temp.next;
}
temp = headB;
while(temp != null) {
if(set.contains(temp)) {
return temp;
}
temp = temp.next;
}
return null;
}
}
双指针法:
/**
* 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 tempA = headA;
ListNode tempB = headB;
while(tempA != tempB) {
tempA = tempA == null ? headB : tempA.next;
tempB = tempB == null ? headA : tempB.next;
}
return tempA;
}
}
暴力解法:
/**
* 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) {
int lenA = 0;
int lenB = 0;
ListNode tempA = headA;
ListNode tempB = headB;
// 确定链表A的长度
while(tempA != null) {
tempA = tempA.next;
lenA++;
}
// 确定链表B的长度
while(tempB != null) {
tempB = tempB.next;
lenB++;
}
// 临时节点复位
tempA = headA;
tempB = headB;
// 使链表A为最长的
if(lenB > lenA) {
// swap(lenA, lenB)
int tempLen = lenA;
lenA = lenB;
lenB = tempLen;
// swap(tempA, tempB)
ListNode tempNode = tempA;
tempA = tempB;
tempB = tempNode;
}
int gap = lenA - lenB; // 长度差
// 使tempA和tempB在同一起点上
while(gap-- > 0) {
tempA = tempA.next;
}
// 遍历
while(tempA != null) {
if(tempA == tempB) {
return tempA;
}
tempA = tempA.next;
tempB = tempB.next;
}
return null;
}
}
标签:tempB,tempA,ListNode,two,next,链表,null,linked
From: https://www.cnblogs.com/ahci316/p/17641856.html