160. Intersection of Two Linked Lists

本文介绍两种高效查找两单链表相交起始节点的方法,包括通过调整链表指针位置实现同步遍历及利用长度差提前遍历较长链表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

Write a program to find the node at which the intersection of two singly linked lists begins.


For example, the following two linked lists:

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

begin to intersect at node c1.

Notes:

  • If the two linked lists have no intersection at all, return null.
  • The linked lists must retain their original structure after the function returns.
  • You may assume there are no cycles anywhere in the entire linked structure.
  • Your code should preferably run in O(n) time and use only O(1) memory.

题意:

写一个程序去找到两个单链表节点相交的开始节点。

note:

1、如果两个单链表没有相交部分,则返回null;

2、链表函数返回后必须保留链表原来的结构;

3、可以假设在整个链表结构中任何地方都没有循环;

4、代码最好是O(n)时间复杂度,O(1)空间复杂度;


思路一:

直接检测两个节点是否相同,相同就返回,否则持续向下走,对于两个长度不一的链表,短的完了之后连接上长的链表起点,长的链表完了之后连接上短的链表起点,形成长度相等的链表,则相当于在第二遍轮训链表时一定可以找到相同的节点,否则为NULL。

代码:C++版:52ms

/**
 * 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* curA = headA;
        ListNode* curB = headB;
        
        while(curA != curB) {
            curA = curA ? curA->next : headB;
            curB = curB ? curB->next : headA;
        }
        
        return curA;
    }
};
思路二:

比较两个链表的长度,使长的链表先走到与短链表相同的长度时,两个链表开始一起走,保证能遇到相同的部分。

代码:java版:3ms

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null) return null;
        int lenA = length(headA);  //计算链表长度
        int lenB = length(headB);
        int count = Math.abs(lenA - lenB);  //计算两个链表长度差
        while(count > 0){    //使两个链表走到长度相等的位置
            if (lenA > lenB){
                headA = headA.next;
            }else{
                headB = headB.next;
            }
            count--;
        }
        
        while (headA != null && headB != null){  //判断链表节点是否相同
            if (headA.val == headB.val) return headA;  //直接判断节点val值貌似不严谨
            headA = headA.next;
            headB = headB.next;
        }
        
        return null;
    }
    
    private int length(ListNode head){ //检测链表长度函数
        if(head == null) return 0;
        int length = 0;
        while (head != null) {
            length++;
            head = head.next;
        }
        return length;
    }
}

代码:java版:2ms!直接判断节点更严谨

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null) return null;
        int lenA = length(headA);  //计算链表长度
        int lenB = length(headB);
        
        while(lenA > lenB){
            headA = headA.next;
            lenA--;
        }
        
        while(lenA < lenB){
            headB = headB.next;
            lenB--;
        }
        
        while(headA != headB){
            headA = headA.next;
            headB = headB.next;
        }
        
        return headA;
    }
    
    private int length(ListNode head){
        if(head == null) return 0;
        int length = 0;
        while (head != null) {
            length++;
            head = head.next;
        }
        return length;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值