判断两个链表是否相交可以用HashSet,但是HashSet需要额外的空间。所以这里使用双指针的解法。

160-相交链表

双指针1

这里有一个问题就是两条链表A和B可能不一样长,这样两个指针p1和p2不能同时指向相交节点c1上。 所以我们让p1遍历完链表A后再去遍历链表B,p2遍历完链表B之后去遍历链表A,这样两条链表就连接在了一起。这样拼接之后,就可以让p1和p2同时进入公共部分,也就是同时到达相交节点c1。
image.png

  1. public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
  2. //p1只想链表A的头节点,p2指向链表B的头节点
  3. ListNode p1 = headA, p2 = headB;
  4. while(p1 != p2){
  5. // p1 走一步,如果走到 A 链表末尾,转到 B 链表
  6. if(p1 == null){
  7. p1 = headB;
  8. }else{
  9. p1 = p1.next;
  10. }
  11. // p2 走一步,如果走到 B 链表末尾,转到 A 链表
  12. if(p2 == null){
  13. p2 = headA;
  14. }else{
  15. p2 = p2.next;
  16. }
  17. }
  18. return p1;
  19. }

双指针2

这种解法也是双指针,也很好理解。既然「寻找两条链表的交点」的核心是p1和p2两个指针同时到达相交节点c1,那么我们可以先计算两条链表的长度,让p1和p2到达尾部的距离相同来做到这第一点。

  1. public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
  2. int lenA = 0, lenB = 0;
  3. //计算两条链表长度
  4. for(ListNode p1 = headA; p1 != null; p1 = p1.next){
  5. lenA++;
  6. }
  7. for(ListNode p2 = headB; p2 != null; p2 = p2.next){
  8. lenB++;
  9. }
  10. // 让 p1 和 p2 到达尾部的距离相同
  11. ListNode p1 = headA, p2 = headB;
  12. if(lenA > lenB){
  13. for(int i = 0; i < lenA - lenB; i++){
  14. p1 = p1.next;
  15. }
  16. }else{
  17. for(int i = 0; i < lenB - lenA; i++){
  18. p2 = p2.next;
  19. }
  20. }
  21. // 看两个指针是否会相同,p1 == p2 时有两种情况:
  22. // 1、要么是两条链表不相交,他俩同时走到尾部空指针
  23. // 2、要么是两条链表相交,他俩走到两条链表的相交点
  24. while(p1 != p2){
  25. p1 = p1.next;
  26. p2 = p2.next;
  27. }
  28. return p1;
  29. }