leetcode-pp / 91alg-5-daily-check

91 天学算法第五期打卡
55 stars 14 forks source link

【Day 10 】2021-09-19 - 160. 相交链表 #25

Open azl397985856 opened 3 years ago

azl397985856 commented 3 years ago

160. 相交链表

入选理由

暂无

题目地址

https://leetcode-cn.com/problems/intersection-of-two-linked-lists/

前置知识

lizzy-123 commented 3 years ago

思路

  1. 使用暴力法,循环2个链表,查找到相同点,但是这种方法到时间过限制。
  2. 所以可以将暴力法该为vector存储A链表节点,然后在遍历B节点时,判断下是否存在于vector之中。
  3. 快慢指针法。快慢指针大部分用于链表中,可以方便快速得到所需解,例如查找中位数,判断是否链表为环,查找倒数第K个节点。

代码 ‘ ListNode getIntersectionNode(ListNode headA, ListNode headB) { //上面方法超过时间限制,将上面方法改为哈希表,会减少时间消耗 //下面采用双指针方法 ListNode nodeA = headA; ListNode * nodeB = headB;

   if(headA==NULL||headB==NULL) return NULL;
   while(1)
   {
       if(nodeA==nodeB) return nodeB;
       if(nodeA==NULL)nodeA = headB;
       else nodeA = nodeA->next;
       if(nodeB==NULL)nodeB = headA;
       else nodeB = nodeB->next;
   }
}’

复杂度分析 时间复杂度:O(m+n) 空间复杂度:O(1)

last-Battle commented 3 years ago

思路

关键点

代码

C++ Code:


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) {
            return nullptr;
        }

        auto lenA = getLen(headA);
        auto lenB = getLen(headB);
        auto diff = abs(lenA - lenB);

        if (lenA > lenB) {
            while (diff--) {
                headA = headA->next;
            }
        } else {
            while (diff--) {
                headB = headB->next;
            }
        }

        while (headA != nullptr && headB != nullptr) {
            if (headA == headB) {
                return headA;
            }

            headA = headA->next;
            headB = headB->next;
        }

        return nullptr;
    }

    int getLen(ListNode* head) {
        int res = 0;
        while (head != nullptr) {
            ++res;
            head = head->next;
        }

        return res;
    }
};

复杂度分析

令 n 为链表长度。

carterrr commented 3 years ago

/**

yingliucreates commented 3 years ago

link:

https://leetcode.com/problems/intersection-of-two-linked-lists/

思路:

代码 Javascript

const getIntersectionNode = function(headA, headB) {
    if (!headA || !headB) return null;
    var curA = headA;
    var curB = headB;
    while (curA != curB) {
        curA = curA == null ? headB : curA.next;
        curB = curB == null ? headA : curB.next;
    }
    return curA;
  };
};

复杂度分析

时间 O(m+n) 空间 O(m+n)

wangyifan2018 commented 3 years ago
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    if headA == nil || headB ==nil {
        return nil
    }
    pa, pb := headA, headB
    count := 0
    for pa != pb {
        if pa == nil {
            pa = headB
            count++
        } else {
            pa = pa.Next
        }
        if pb == nil {
            pb = headA
            count++
        } else {
            pb = pb.Next
        }
        if count > 2 {
            return nil
        }      
    }
    return pa
}
xbhog commented 3 years ago

160. 相交链表

解题思路:

采用set来实现,先遍历一遍A,在遍历B,如果遍历B时,节点存在 则返回;该解法为简单题;

Java代码段:

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        Set<ListNode> set = new HashSet<>();
        while(headA != null){
            set.add(headA);
            headA = headA.next;
        } 
        ListNode cur = headB;
        while(cur != null){
            if(set.contains(cur)){
                return cur;
            }
            cur = cur.next;
        } 
        return null;
    }
}

复杂度分析:

其中 m 和 n 是分别是链表 headA 和 headB 的长度

时间复杂度:O(m+n) 都要遍历A和B

空间复杂度:o(m) 要保存A中的节点信息

newbeenoob commented 3 years ago

思路


相向运动相遇问题 先计算长度,得出长短链表的差值diff,让长链表先走diff个距离,然后让长短链表以同速向前走,直到两指针相撞(有交点)或者两指针都走到了末尾(==null)代表没有交点

代码:JavaScript

var getIntersectionNode = function(headA, headB) {

    if (!headA || !headB) return null;

    let p1 = headA , p2 = headB;

    // 先计算长度
    let len1 = 0 , len2 = 0;
    while(p1) {
        p1 = p1.next;
        len1++;
    }

    while(p2) {
        p2 = p2.next;
        len2++;
    }
    let fast , slow;
    let diff = Math.abs(len1 - len2);
    if (len1 > len2) {
        fast = headA; slow = headB;
    } else {
        fast = headB; slow = headA;
    }

    while(diff){
        --diff;
        fast = fast.next;
    }

    while(fast && slow && fast !== slow) {
        fast = fast.next;
        slow = slow.next;
    }

    return slow;
};

复杂度分析


标签


链表 , 双指针

AnhTom2000 commented 3 years ago

思路

先算出链表A与链表B的length,然后算出两者之间的差值diffrence,让两者中最长的的链表先走diffrence步,再让较短的链表与长链表一起遍历,如果两个链表结点相同则说明两个链表相交了。

代码:Java

public class Solution {
    public int getLen(ListNode head){
      ListNode  temp = head;
      int index = 0;
      while(temp != null){
        index++;
        temp = temp.next;
      }
      return index;
    }
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
       int a = getLen(headA);
       int b = getLen(headB);
       int difference = Math.abs(a - b);
       ListNode ta = headA;
       ListNode tb = headB;

       if(b > a){
         for(int i = 0; i < difference ;i ++){
           tb = tb.next;
         }
         while(tb != null){
           if(tb == ta) return tb;
           tb = tb.next;
           ta = ta.next;
         }
       }else {
         for(int i = 0; i < difference ;i++){
           ta = ta.next;
         }
         while(ta != null){
           if(ta == tb) return ta;
           ta = ta.next;
           tb = tb.next;
         }
       }

       return null;
    }
}

复杂度分析

时间复杂度:O(n)

空间复杂度:O(1)

ychen8777 commented 3 years ago

思路

分别遍历两个链表获取长度,移动标记在长链表的指针,使其到长链表末尾的长度和短链表整体长度一致,两个指针分别遍历两个链表,两个指针指向的ListNode相同时,return 该ListNode

代码

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {

        int lengthA = getLength(headA);
        int lengthB = getLength(headB);

        ListNode curA = headA;
        ListNode curB = headB;

        while (lengthA > lengthB && curA != null) {
            lengthA--;
            curA = curA.next;
        }

        while (lengthB > lengthA && curB != null) {
            lengthB--;
            curB = curB.next;
        }

        while(curA != null && curB != null) {
            if (curA == curB) {
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }

        return null;

    }

    public int getLength(ListNode head) {
        if (head == null) {
            return 0;
        }

        int length = 1;
        ListNode cur = head;

        while(cur.next != null) {
            length++;
            cur = cur.next;
        }

        return length;

    }

}

复杂度

时间: O(m+n) \ 空间: O(1)

Francis-xsc commented 3 years ago

思路

双指针

代码


class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* a=headA,*b=headB;
        while(a!=b)
        {
            a=a->next;
            b=b->next;
            if(!a&&!b)
                return nullptr;
            if(!a)
                a=headB;
            if(!b)
                b=headA;
        }
        return a;
    }
};

复杂度分析

bingyingchu commented 3 years ago

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:    
        cur1 = headA
        cur2 = headB

        while cur1 != cur2:
            cur1 = cur1.next if cur1 else headB
            cur2 = cur2.next if cur2 else headA
        return cur1

Time: O(a+b) where a is length of list A and b is length of list B
Space: O(1)
kennyxcao commented 3 years ago

160. Intersection of Two Linked Lists

Intuition

  ----A----
           ----C----
------B----

A + C + B == B + C + A

Code

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
const getIntersectionNode = function(headA, headB) {
  if (!headA || !headB) return null;
  let a = headA;
  let b = headB;
  while (a !== b) {
    a = a === null ? headB : a.next;
    b = b === null ? headA : b.next;
  }
  return a;
};

Complexity Analysis

miss1 commented 3 years ago
var getIntersectionNode = function(headA, headB) {
  let p1 = headA;
  let p2 = headB;
  while (p1 !== p2) {
    p1 = p1 ? p1.next : headB;
    p2 = p2 ? p2.next : headA;
  }
  return p1;
};
yuxiangdev commented 3 years ago

public ListNode getIntersectionNode(ListNode headA, ListNode headB) { int lenA = length(headA); int lenB = length(headB); while (lenA > lenB) { headA = headA.next; lenA--; } while (lenB > lenA) { headB = headB.next; lenB--; } while (headA != headB) { headA = headA.next; headB = headB.next; } return headA; }

private int length(ListNode head) {
    int len = 0;
    while (head != null) {
        head = head.next;
        len++;
    }
    return len;
}
YQYCS commented 3 years ago

思路

参考题解

代码

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        A = headA
        B = headB
        while A != B:
            A = A.next if A else headB
            B = B.next if B else headA
        return A

复杂度

时间复杂度 O(a+b) 空间复杂度 O(1)

joeytor commented 3 years ago

思路

遍历链表A, 将所有节点加入 set

遍历链表B, 如果节点在 set 中, 那么就是相交的节点, 返回这个节点

否则就返回 None, 代表没有相交的节点

代码

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        d = set()
        while headA:
            d.add(headA)
            headA = headA.next

        while headB:
            if headB in d:
                return headB
            headB = headB.next

        return None

复杂度

空间复杂度: O(m+n) m 是链表 A 的长度, n 是链表 B 的长度, 因为最坏遍历两个链表各一次

时间复杂度: O(m+n) m 是链表 A 的长度, n 是链表 B 的长度, 因为最坏可能遍历两个链表的所有元素

okbug commented 3 years ago

代码

C++

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* p1 = headA;
        ListNode* p2 = headB;
        while (p1 != p2) {
            p1 = p1 ? p1->next : headB;
            p2 = p2 ? p2->next : headA;
        }

        return p1;
    }
};
ChiaJune commented 3 years ago

思路

讲义(基础篇) -> 链表

代码

var getIntersectionNode = function(headA, headB) {
  var a = headA, b = headB;
  while (a != b) {
    a = a ? a.next : null;
    b = b ? b.next : null;
    if (a == null && b == null) return null;
    if (a == null) a = headB;
    if (b == null) b = headA;
  }
  return a;
};

复杂度

时间:O(n) 空间:O(1)

kofzhang commented 3 years ago

思路

a+b与b+a长度相同

代码(Python3)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:

        t1=headA
        t2=headB
        while t1 != t2:
            t1=t1.next if t1 else headB
            t2=t2.next if t2 else headA
        return t1

复杂度

learning-go123 commented 3 years ago

思路

代码

Go Code:


/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    nHeadA,nHeadB := headA, headB
    for nHeadA != nHeadB {

        nHeadA = nHeadA.Next
        nHeadB = nHeadB.Next

        if nHeadA == nil && nHeadB == nil {
            return nil
        }

        if nHeadA == nil {
            nHeadA = headB
        }
        if nHeadB == nil {
            nHeadB = headA
        }
    }
    return nHeadA
}

复杂度分析

令 n 为数组长度。

erik7777777 commented 3 years ago

思路

straightforward way is to use a set to record, when we find the first node we can't add to set, it is the start node of the intersection part

代码

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) return null;
        Set<ListNode> visited = new HashSet<>();
        while (headA != null || headB != null) {
            if (headA != null && !visited.add(headA)) return headA;
            if (headB != null && !visited.add(headB)) return headB;
            headA = headA == null ? headA : headA.next;
            headB = headB == null ? headB : headB.next;
        }
        return null;
    }

复杂度

time : O(m + n) space : strictly the same as time O(m + n) m, n are the length of two lists

idea

we can do better, use math to deal with it. the difference of length of two list is the difference of the different part of lists

denote the length into two parts

different + same:

a + c

b + c

when we know the value of |a - b|, we can find the first node of the intersection part

a + c + b = b + c + a

JinhMa commented 3 years ago

/**

leolisgit commented 3 years ago

思路

  1. 如果A和B的头节点都距离交点一样远,那么同时移动,必然相交。分别求出A,B的长度,然后在长度较长的链表上,先移动n步,n为两个链表的长度差。
  2. 看别人的题解,发现了一个更简单的思路,就是让链表形成环,如果相交,就会在交点处相遇,否则就是在为null的尾节点相遇。

代码

Solution - 1:

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int lenA = 1;
        int lenB = 1;

        ListNode hA = headA;
        ListNode hB = headB;

        while (hA != null) {
            lenA++;
            hA = hA.next;
        }

        while (hB != null) {
            lenB++;
            hB = hB.next;
        }

        while (lenA > lenB) {
            headA = headA.next;
            lenA--;
        }

        while (lenB > lenA) {
            headB = headB.next;
            lenB--;
        }

        while (headA != null && headB != null) {
            if (headA == headB) {
                return headA;
            }
            headA = headA.next;
            headB = headB.next;
        }
        return null;
    }

Solution - 2

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) return null;

        ListNode a = headA;
        ListNode b = headB;
        while (a != b) {
            a = (a == null) ? headB : a.next;
            b = (b == null) ? headA : b.next;
        }
        return a;
    }

复杂度:

时间:O(n)
空间:O(1)

TimmmYang commented 3 years ago

思路

双指针,链表A或B同时开始遍历,遍历到最后一个节点后分别指向对方的头节点进行第二次遍历,这样如果相交就会在相交节点两指针相遇,返回即可;不相交就会第二次触底,这时返回即可。

代码

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        p1, p2 = headA, headB
        flag1 = flag2 = 0
        while p1 != p2:
            p1 = p1.next
            p2 = p2.next
            if p1 == None:
                p1 = headB
                flag1 += 1
            if p2 == None:
                p2 = headA
                flag2 += 1
            if flag1 >= 2 or flag2 >= 2:
                return None
        return p1

复杂度

时间:O(n) n为两链表长度之和 空间:O(1)

chang-you commented 3 years ago

Thinking

Add pathA to the tail to PathB, and add PathB to the tail of path A.
if they have intersection, the condition while(a != b) will terminate, and the node that a is at is what we want to return.
Else a will just reach the end of the combined list, which is null, return a <-> return null.

Java Code

/**
     *
     A:          a1 → a2
                         ↘
                         c1 → c2 → c3
                         ↗
     B:     b1 → b2 → b3
 .
     begin to intersect at node c1.

     A : a1 → a2 -> c1 → c2 → c3 -> b1 → b2 → b3 -> *c1*→ c2 → c3
     B : b1 → b2 → b3 -> c1 → c2 → c3 -> a1 → a2 -> *c1* → c2 → c3

     time : O(m + n);
     space : O(1);

     */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) return null;
        ListNode a = headA;
        ListNode b = headB;
        while (a != b) {
            a = a == null ? headB : a.next;
            b = b == null ? headA : b.next;
        }
        return a;
    }
}

Complexity:

Time = O(m + n) : Traverse both linkedlist twice.
Space= O(1)

akxuan commented 3 years ago

从长度相同的部分开始找

o(n)

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        dummy_a,dummy_b = ListNode(0),ListNode(0)
        dummy_a.next,dummy_b.next = headA, headB

        lenA,lenB = 0,0
        while headA :
            lenA+=1
            headA = headA.next
        while headB:
            lenB+=1
            headB = headB.next

        headA , headB = dummy_a.next, dummy_b.next

        while headA and headB:
            if lenA == 0 or lenB == 0:
                break

            if lenA > lenB :
                headA = headA.next
                lenA-=1
            elif lenA < lenB:
                headB = headB.next
                lenB-=1
            else:
                if headB == headA:
                    return headB
                else:
                    headA = headA.next

                    headB = headB.next
                    lenA-=1
                    lenB -=1
JinMing-Gu commented 3 years ago
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode *> visited;
        ListNode *temp = headA;
        while (temp != nullptr) {
            visited.insert(temp);
            temp = temp->next;
        }
        temp = headB;
        while (temp != nullptr) {
            if (visited.count(temp)) {
                return temp;
            }
            temp = temp->next;
        }
        return nullptr;
    }
};
q815101630 commented 3 years ago

只说为什么 while a != b 因为遍历到最后 一定会是None == None 情况

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        a = headA
        b = headB
        while a != b:
            if a:
                a = a.next
            else:
                a = headB
            if b:
                b = b.next
            else:
                b = headA
        # if not a or not b:
        #     return None
        return a

Time: O(n)

cicihou commented 3 years ago

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not headA or not headB:
            return

        dic = {}
        while headA:
            dic[headA] = None
            headA = headA.next
        while headB:
            if headB in dic:
                return headB
            else:
                headB = headB.next
xieyj17 commented 3 years ago
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        p1 = headA
        p2 = headB
        while p1 != p2:
            if p1 is None:
                p1 = headB
            else:
                p1 = p1.next
            if p2 is None:
                p2 = headA
            else:
                p2 = p2.next
        return p1 

之前碰到过一次的题目,历遍两次找到相交的点

Time O(n)

Space O(1)

ghost commented 3 years ago

题目

  1. Intersection of Two Linked Lists

思路

Figured out the solution using hash table, get the constant space way by reading the solution. Using the same distance logic for this quesion

代码

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        a = headA
        b = headB

        while(a != b):
            if not a:
                a = headB
            else:
                a = a.next

            if not b:
                b = headA
            else:
                b = b.next

        return b

复杂度

Space: O(1) Time: O(N)

AgathaWang commented 3 years ago

哈希表和双指针


class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        # 双指针
        # a = headA
        # b = headB
        # while a != b:
        #     # 注意if a not a.next, because a could handle no intersect
        #     a = a.next if a else headB  
        #     b = b.next if b else headA
        # return a

        # 哈希表,set()形式,list会超时
        s = set()
        # s = []
        a = headA
        b = headB
        while a:
            s.add(a)
            # s.append(a)
            a = a.next
        while b:
            if b in s:
                return b 
            b = b.next
        return None

哈希表 - 时间复杂度:O(N), 空间复杂度O(N) 双指针 - 时间复杂度:O(N), 空间复杂度O(1)

kendj-staff commented 3 years ago
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode A = headA;
        ListNode B = headB;
        while (A != B) {
            A = A == null ? headB : A.next;
            B = B == null ? headA : B.next;
        }
        return A;
    }
}
chun1hao commented 3 years ago
var getIntersectionNode = function(headA, headB) {
    let dummyA = headA
    let dummyB = headB
    while(dummyA !== dummyB){
        dummyA = dummyA ? dummyA.next : headB
        dummyB = dummyB ? dummyB.next : headA
    }
    return dummyB
};

时间:O(N) 空间:O(1)

shixinlovey1314 commented 3 years ago

Title:160. Intersection of Two Linked Lists

Question Reference LeetCode

Solution

If list A and list B have intersection, they would have the same tail node (And a subset list of common nodes). When list A and list B has different length, we just need to fastwind the 'longger' list till their remain length are the same, then we can compare each node on the two lists to find the intersection node.

Algo:

  1. Go through list A, get lengthA and tailA.
  2. Go through list B, get lengthB and tailB.
  3. if tailA != tailB, return NULL.
  4. compare lenghtA and lengthB, find the longger list.
  5. fastwind the logger list till the two lists have same remain length
  6. Traverse two lists and find the intercestion node.

Code

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (!headA || !headB)
            return NULL;

        int lenA = 1;
        int lenB = 1;
        ListNode* nodeA = headA;
        ListNode* nodeB = headB;

        while (nodeA && nodeA->next) {
            lenA++;
            nodeA = nodeA->next;
        }

        while (nodeB && nodeB->next) {
            lenB++;
            nodeB = nodeB->next;
        }

        if (nodeA != nodeB)
            return NULL;

        ListNode* longList = NULL;
        ListNode* shortList = NULL;

        if (lenA > lenB) {
            longList = headA;
            shortList = headB;
        } else {
            longList = headB;
            shortList = headA;
        }

        int delta = abs(lenA - lenB);

        while (delta--) {
            longList = longList->next;
        }

        while (longList && shortList) {
            if (longList == shortList)
                break;
            longList = longList->next;
            shortList = shortList->next;
        }

        return longList;
    }
};

Complexity

Time Complexity and Explaination

O(M+N)

Space Complexity and Explaination

O(1)

Better Solution

The previouse solution has O(M+N) time complexity and O(1) space complexity, but the code is quite long and error prone. We could use an even simpler approach.

Let's say the length of the common list is lenC. The length of the exclusive partion of the listA is lenA The length of the exclusive partion of the listB is lenB.

We know that lenA + lenC + lenB = lenB + lenC + lenA

So we can simplify the solution: pA point to the head of list A pB point to the head of list B. if pA reach the end of list A, point pA to list B. if pB reach the end of list B, point pB to list A. when pA == pB, we have found the intersection.

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* pA = headA;
        ListNode* pB = headB;

        while (pA != pB) {
            pA = pA? pA->next : headB;
            pB = pB? pB->next : headA;
        }

        return pA;
    }
};

Complexity

Time Complexity and Explaination

O(M+N)

Space Complexity and Explaination

O(1)

yanjyumoso commented 3 years ago
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:

        if not headA or not headB:
            return None

        pa, pb = headA, headB

        while pa != pb:
            pa = headB if not pa else pa.next
            pb = headA if not pb else pb.next
        return pa
doveshnnqkl commented 3 years ago

思路

双指针 同时遍历a,b链表,当遍历到a末尾,重定位到b链表头,当遍历到b末尾,重定位到a链表头,如过有a等于b 返回该节点,如果有a等于b等于Null,说明没有交点

代码

java

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode a = headA;
        ListNode b = headB;
        while(a != b){
              a = a.next;
              b = b.next;
              if(a == null && b == null){
                  return null;
              }
              if(a == null){
                  a = headB;
              }
              if(b == null){
                  b = headA;
              }

        } 
        return a;

    }
}

复杂度

时间复杂度O(n+m) n:a链表长度,m:b链表长度 空间复杂度O(1)

SunnyYuJF commented 3 years ago

思路

a1->a2->c1->c2->b1->b2->b3->c1->c2
b1->b2->b3->c1->c2->a1->a2->c1->c2

代码 Python

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        if not headA or not headB:
            return None
        cur1=headA
        cur2=headB
        while cur1!=cur2:
            if cur1:
                cur1=cur1.next
            else:
                cur1 = headB

            if cur2:
                cur2=cur2.next
            else:
                cur2 = headA

        return cur1   

复杂度分析

时间复杂度: O(M+N)
空间复杂度: O(1)

fzzfgbw commented 3 years ago

思路

n1+n2 - s = n2+n1 - s (n1,n2分别为链表长度,s为交叉点之后的路径长度)

代码

func getIntersectionNode(headA, headB *ListNode) *ListNode {
    if headA == nil || headB == nil {
        return nil
    }
    dummyA := headA
    dummyB := headB
    for  headA != headB {
        if headA.Next == nil && headB.Next == nil  {
            return nil
        }
        if headA.Next == nil {
            headA = dummyB
        } else {
            headA = headA.Next
        }
        if headB.Next == nil {
            headB = dummyA
        } else {
            headB = headB.Next
        }

    }
    return headA
}

复杂度分析

comst007 commented 3 years ago

160. 相交链表


思路

代码


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* pa = headA;
        ListNode* pb = headB;
        while(pa != pb){
            if(pa){
                pa = pa ->next;
            }else{
                pa = headB;
            }
            if(pb){
                pb = pb -> next;
            }else{
                pb = headA;
            }
        }
        return pa;

    }
};

复杂度分析

Daniel-Zheng commented 3 years ago

思路1

遍历两个单链表,可以用hashset存储headA,再判断headB中是否有交点。

代码(C++)

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode*> visited;
        ListNode* temp = headA;
        while (temp != nullptr) {
            visited.insert(temp);
            temp = temp->next;
        }
        temp = headB;
        while (temp != nullptr) {
            if (visited.count(temp)) return temp;
            temp = temp->next;
        }
        return nullptr;
    }
};

复杂度分析

思路2

双指针,同时遍历headA + headB,headB + headA,如有交点一定会有相等的节点。

代码(C++)

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* A = headA;
        ListNode* B = headB;
        while (A != B) {
            A = A != nullptr ? A->next : headB;
            B = B != nullptr ? B->next : headA;
        }
        return A;
    }
};

复杂度分析

ruohai0925 commented 3 years ago

思路

关键点

代码

Python3 Code:


class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not headA or not headB:
            return None
        pa, pb = headA, headB
        while pa != pb:
            pa = pa.next if pa else headB
            pb = pb.next if pb else headA
        return pa

复杂度分析

Time: O(len(A) + len(B) - len(common(A, B))

Space: O(1)

xixvtt commented 3 years ago

占坑稍等回答

jsu-arch commented 3 years ago

Method One: Hash Table

Discussion:

  1. Whether the two linked-list will be empty.
  2. If they intersect at one node, will the node have the same value? -yes

Method:

  1. We store all the nodes in List A in hash table, traverse all the node in list B and then check whether node in list B exists in the hash table. If it does, return it as it must be at the intersection node. If not, we go to the end of list A and cannot find an intersection node, return null.

Important points:

1. Check the condition if either of the list is empty.

Code


class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        node_in_A = set()
        
        while headA is not None:
            node_in_A.add(headA)
            headA = headA.next
        
        while headB is not None:
            #If in the node_a_set we found headB, we return the node
            if headB in node_in_A:
                return headB
            headB = headB.next
            
        return None

Complexity Analysis

Method Two: Two Pointers

Discussion:

  1. Whether the two linked-list will be empty.
  2. If they intersect at one node, will the node have same value?
  3. Why do we wan to use two pointers? Because we want to get the Space Complexity DOWN!

Method:See your notes

Important points:

NA

Code


def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        if not headA or not headB:
            return None

        pA = headA
        pB = headB

        while (pA != pB):
            if pA is None:
                pA = headB
            else:
                pA = pA.next
            if pB is None:
                pB = headA
            else:
                pB = pB.next
        return pA

Complexity Analysis

bolunzhang2021 commented 3 years ago
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode a=headA;
        ListNode b=headB;
        while(a!=b)
        {
        if(a==null)
         a=headB;
         else
         a=a.next;
         if(b==null)
         b=headA;
         else
         b=b.next;
        }
        return a;

    }
}

时间复杂度O(N) 空间复杂度O(1)

Okkband commented 3 years ago
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) return nullptr;
        ListNode* pA = headA;
        ListNode* pB = headB;
        while(pA != pB){
            if (pA == nullptr){
                pA = headB;
            } else {
                pA = pA->next;
            }
            if (pB == nullptr){
                pB = headA;
            } else {
                pB = pB->next;
            }
        }
        return pA;
    }
};

时间复杂度:O(m+n), m,n 为两链表的长度

空间复杂度:O(1)

pangjiadai commented 3 years ago

思路

Python3

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        A = headA
        B = headB

        while A != B:
            A = A.next if A else headB
            B = B.next if B else headA

        return A

复杂度

laurallalala commented 3 years ago

代码

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        a_len, b_len = 0, 0
        pa, pb = headA, headB
        while pa:
            pa = pa.next
            a_len += 1
        while pb:
            pb = pb.next
            b_len += 1
        pmax = headB if b_len > a_len else headA
        pmin = headB if b_len <= a_len else headA
        diff = abs(a_len-b_len)
        while diff > 0:
            pmax = pmax.next
            diff -= 1
        while pmin:
            if pmin == pmax:
                return pmin
            else:
                pmin = pmin.next
                pmax = pmax.next
        return None

复杂度

QiZhongdd commented 3 years ago
var getIntersectionNode = function(headA, headB) {
    let nodeA=headA;
    let nodeB=headB;
    while(nodeA&&nodeB){
        if(nodeA===nodeB){
           return nodeA
        } 
        nodeA=nodeA.next;
        nodeB=nodeB.next;
        if(nodeA===null&&nodeB){
            nodeA=headB
        }
        if(nodeB===null&&nodeA){
            nodeB=headA
        }
    }
    return null
};

时间复杂度:o(n+m),空间o(1)

lilyzhaoyilu commented 3 years ago

传统思路,这期我的重点在锻炼写c++而不是思路上,所以就不写思路了(^▽^) Apex的服务器啥时候能修好啊

思路 哈希表

set就是hashmap/哈希表的一种;
此处的是没有顺序的。JS的一般默认是有序的:D

根据Lucifer的建议改进了一下,添加了数哪个list更小的countWhoIsSmaller
根据更小的结果来选择谁作为哈希表(unsorted_set)的存储对象,以达到优化空间的目的。
当然这个优化不是必须的。

代码 CPP

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode *>visited;

        std::string result = countWhoIsSmaller(headA, headB);

        ListNode *temp = result == "A" ? headA : headB;

        while(temp != nullptr){
            visited.insert(temp);
            temp = temp->next;
        }

        temp = result == "A" ? headB : headA;

        while(temp != nullptr){
            if(visited.count(temp)){
                return temp;
            }
            temp = temp->next;
        }
        return nullptr;
    }
private:
    std::string countWhoIsSmaller(ListNode *headA, ListNode *headB){
        int sizeA = 0, sizeB = 0;
        ListNode *count = headA;
        while(count != nullptr){
            sizeA++;
            count = count->next;
        }
        count = headB;
        while(count != nullptr){
            sizeB++;
            count = count->next;
        }
        if (sizeA >= sizeB){
            return "B";
        }else{
            return "A";
        }
    }
};

复杂度分析

时间复杂度:O(n + m) n is the size of the list that starts with HeadA, m is ... headB
空间复杂度:O(min(m,n))

思路 双指针

代码 CPP

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA == nullptr || headB == nullptr){
            return nullptr;
        } 
        ListNode *pa = headA, *pb = headB;
        while(pa != pb){
            pa = pa == nullptr ? headB : pa->next;
            pb = pb == nullptr ? headA : pb->next;
        }
        return pa;
    }
};

复杂度分析

时间复杂度:O(n + m)
空间复杂度:O(1)