157. Intersecion of Two Linked Lists

题目

给定两个单链表头 headA headB。返回两个链表相交的节点,如果两个链表不相交,返回 null。

解析

假设两个链表相交,那么当 A 遍历到相交节点的时候,如何判断这个节点是否在 B 上?
假设有两条路在某一处之后是完全相交的,那么从这条路两端相向而行,一定能相遇。
所以,对于这个问题,首先从 A 节点开始,将 A 链表反向。得到 A 的末尾 tailA。
然后从 headB 和 tailA 相向而行,如果相遇,则相遇节点就是交集,如果不相遇,则没有交集返回空。
题目要求链表最终应该还原,那么可以在 tailA 反向的同时进行链表反向操作。

伪代码

for cur != nil
  cur.next = last
  cur = cur.next
  last = cur
tailA = last

for headB != nil && tailA != nil
  if headB == tailA || headB.next == tailA || tailA.next == headB  
    find = ?
  tailA.next = last
  last = tailA
  tailA = tailA.next

错误

以上代码逻辑并不能找到相交节点,因为在反向同步递进的过程中可能错过。

思路2

如果要让两个链表同时步进相遇,需要两个链表长度相同。
那么我们只需要让长一点的链表先走几布,让两个链表一样长。然后再同时步进即可。

伪代码

a = len(A)
b = len(B)

v = a-b
if v > 0
  A = A-> |v|
if v<0
  B = A->|v|
for A != nil && B != nil 
  if A == B
    return A
  A=A.next
  B=B.next
return nil

代码

func getIntersectionNode(headA, headB *ListNode) *ListNode {
    na := headA
    nb := headB
    la := lenoflist(headA)
    lb := lenoflist(headB)
    
    v := la - lb
    if v > 0 {
        for i:=0; i < v; i++ {
            na = na.Next
        }
    }
    if v < 0 {
        for i:=v; i<0; i++ {
            nb = nb.Next
        }
    }
    for na != nil {
        if na == nb {
            break
        }
        na=na.Next
        nb=nb.Next
    }
    return na
}

func lenoflist(head *ListNode) int {
    rst := 0
    for head != nil {
        rst++
        head=head.Next
    }
    return rst
}
image.png

后记

看上去好象是很简单的问题,但找不到正确的解决办法?居然没有想到如果后边的交叠,前边的属于多余节点,裁掉多余节点就可以进行同时步进然后找到相同的节点了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容