链表相交问题(双指针法)(java和c语言)

问题描述

给你两个单链表的头节点 headA 和 headB,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null。

方法:双指针

一种高效的方法是使用两个指针,分别从两个链表的头部开始遍历。当一个指针到达链表末尾时,它切换到另一个链表的头部继续遍历。如果两个链表相交,那么这两个指针一定会在某一点相遇,这个相遇点就是相交的起始节点。

实现思路
  1. 初始化两个指针:分别指向链表A和链表B的头节点。
  2. 遍历链表:每次移动一步。
  3. 切换链表:当一个指针到达链表末尾时,将其指向另一个链表的头节点。
  4. 寻找相遇点:继续遍历,直到两个指针相遇。相遇点即为相交的起始节点。

这种方法巧妙地利用了双指针,避免了额外的空间开销,时间复杂度为O(m + n),其中m和n分别是两个链表的长度。

代码实现(Java)
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;
    }
}
代码实现(C)

#include 

struct ListNode {
    int val;
    struct ListNode *next;
};

struct ListNode* getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if (headA == NULL || headB == NULL) return NULL;
    
    struct ListNode *tempA = headA;
    struct ListNode *tempB = headB;
    
    while (tempA != tempB) {
        tempA = tempA == NULL ? headB : tempA->next;
        tempB = tempB == NULL ? headA : tempB->next;
    }
    
    return tempA;
}

为什么这种方法有效?

假设链表A的长度为a + c,链表B的长度为b + c,其中c是相交的部分。

  • 如果a = b,那么两个指针会同时到达相交点。
  • 如果a ≠ b,指针A会先遍历完链表A,然后切换到链表B,指针B会先遍历完链表B,然后切换到链表A。这样,它们总共遍历的长度都是a + b + c,因此会在相交点相遇。

如果没有相交点,两个指针最终都会同时到达链表末尾,即NULL,从而结束循环并返回NULL。

总结

双指针法是一种高效且优雅的解决链表相交问题的方法。通过让两个指针分别遍历两个链表,并在到达末尾时切换到另一个链表,我们可以在不额外占用空间的情况下找到相交的起始节点。希望这篇博客能帮助你理解这一方法,并在实际编码中应用它。

你可能感兴趣的:(链表,c语言,算法,java)