LeetCode160 相交链表

88 阅读2分钟

leetcode.cn/problems/in…

image.png

解法一:双指针

如果用两个指针 p1 和 p2 分别在两条链表上前进,我们可以让 p1 遍历完链表 A 之后开始遍历链表 B,让 p2 遍历完链表 B 之后开始遍历链表 A,这样相当于「逻辑上」两条链表接在了一起,那么就可以让 p1 和 p2同时进入公共部分,也就是同时到达相交节点

image.png

如果说两个链表没有相交点,这个逻辑可以覆盖这种情况的,相当于 c1 节点是空指针 null 嘛,还是可以正确返回 null。

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    p1, p2 := headA, headB
    for p1 != p2{
        if p1 == nil{ // p1 如果走到 A 链表末尾,转到 B 链表
            p1 = headB
        }else {
            p1 = p1.Next
        }
        if p2 == nil{ // p2 如果走到 B 链表末尾,转到 A 链表
            p2 = headA
        }else {
            p2 = p2.Next
        }
    }
    return p1
}

解法二:计算剩余距离

先计算两条链表的长度,然后让 p1 和 p2 距离链表尾部的距离相同,然后齐头并进

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    p1, p2 := headA, headB
    // 计算两个链表的长度
    lenA, lenB := 0, 0
    for p1 != nil{
        p1 = p1.Next
        lenA++
    }
    for p2 != nil{
        p2 = p2.Next
        lenB++
    }
    // 重置遍历起点指针的位置
    p1, p2 = headA, headB
    // 将两个起点调整为距离尾部相同的距离,即走到结尾的步长保持一致
    if lenA > lenB{
        // A链表更长,应该挪动p1
        for i := 0; i<lenA-lenB; i++{
            p1 = p1.Next
        }
    }else if lenB > lenA{ 
        // B链表更长,应该挪动p2
        for i:=0; i<lenB-lenA; i++{
            p2 = p2.Next
        }
    }
    // 如果lenA=lenB,则一开始p1和p2距离尾部距离一样
    // 接下来p1和p2齐头并进,只需要不断判断是否遍历到了同个节点即可
    for p1 != p2{ // 不相交都走到了末尾,都为nil也会命中循环退出条件
        p1 = p1.Next
        p2 = p2.Next
    }
    return p1
}