[LeetCode] Intersection of Two Linked Lists 题解

本文介绍了求解两个链表交点的多种算法,包括暴力枚举、哈希表存储、长度计算法及双指针法,并详细解析了双指针法的原理与实现。

前言

Intersection of Two Linked Lists也是LeetCode的Linked List Tag下的一道题,网上流传着多种做法。

题目

https://leetcode.com/problems/intersection-of-two-linked-lists/
Write a program to find the node at which the intersection of two singly linked lists begins.

QQ截图20160319101728.jpg

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.

题意就是有两串链表,它们可能是有公共部分的,请求出两个链表的交叉点,返回之。
注意如果没有intersection,就返回NULL。解法不能改变原有链表的结构。另外保证链表中任何地方不存在环。最好实现O(n)的时间复杂度和O(1)的空间复杂度。

分析

这个题解法还是不少的。首先能够想到的就是暴力枚举,对于链表A中的每个节点ai,遍历整个链表B,检查B中是否有节点与ai重合。这显然是O(mn)的 时间。

第二种方案,弄个哈希表,遍历链表A,把每个节点的地址存储在哈希表中。然后遍历B,检查链表B中的每个节点bi——如果在哈希表中找到了,则bi就是交点。

第三种方案,长度计算法。设置指针p1、p2分别指向链表A和B的head。通过遍历记录两个链表的长度,lenA和lenB。要注意两个链表的长度可能不相同,如题目所给的样例,lenA=5,lenB=6,我们得到:lenB-lenA=1。根据这个结论,将指针p2从链表B的首节点开始移动1步,即指向第二个节点,p1指向链表A的首节点,然后同时开始遍历,每次走一步,当它们相等时,自然就是两个表的交点。

但是长度计算的方案仍然不是最简洁的做法,接下来我们讨论一个在LeetCode的Discuss区被称为“Really eyes opening algorithm!”的解法,它实际上是一种双指针法
首先做一个假设,如果题目的测试数据中,每一组链表的长度都相等,会怎么样?也就是说,对于上面的长度计算法,所有的lenB都等于lenA,会如何?显然,我们就不需要费神把指针挪来挪去——只需要扔两个指针到A和B的head,然后同时遍历,它俩第一次相等的时候自然就是intersection point。
然而事情没有这么完美,两个链表长度不同的情况,要是还同时遍历的话,它们之间总会出现一定的距离差距。

QQ截图20160319103638.jpg

但是我们可以发现,无论两个链表各自多长,是长度相等还是长度相差很大,它们都满足这样一个公式:a + c+ b = b + c +a

QQ截图20160319104117.jpg

注意这个公式中字母出现的顺序,这意味着我们可以这么做:维护两个指针pA和pB,初始分别指向A和B的head。然后让它们分别遍历整个链表,每步一个节点。当pA到达链表末尾时,让它指向B的头节点;而当pB到达链表末尾时,让它重新指向A的头节点。 继续遍历过程,如果pA在某一点与pB相遇(相等),则pA/pB就是交点。这个过程结束后,每个指针的“路程”都是a + b + c的长度。我们显然得出这样的论断,当两个指针都被重置过一次后,如果遍历继续到某个时刻它们相等,那么这个点一定就是intersection。
这个方案是O(n+m) Time Complexity, O(1) Space Complexity的,也是目前公认的最优解法。

代码

下面给出长度计算法和双指针法的代码:
长度计算法:

 ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *pa=headA,*pb=headB;
        int lengthA=0,lengthB=0;
        while(pa) {pa=pa->next;lengthA++;}
        while(pb) {pb=pb->next;lengthB++;}
        if(lengthA<=lengthB){
            int n=lengthB-lengthA;
            pa=headA;pb=headB;
            while(n) {pb=pb->next;n--;}
        }else{
            int n=lengthA-lengthB;
            pa=headA;pb=headB;
            while(n) {pa=pa->next;n--;}
        }
        while(pa!=pb){
            pa=pa->next;
            pb=pb->next;
        }
        return pa;
    }

双指针法:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
      ListNode * p1 = headA, * p2 = headB;
      if (p1 == NULL || p2 == NULL) return NULL;
      while (p1 != NULL && p2 != NULL && p1 != p2) {
        p1 = p1->next;
        p2 = p2->next;
        if (p1 == p2) return p1;
        if (p1 == NULL) p1 = headB;
        if (p2 == NULL) p2 = headA;
      }
    return p1;
    } 
};
内容概要:本文围绕并网与离网模式下的风光互补制氢合成氨系统,开展容量配置与调度优化的建模与仿真研究,基于Python代码实现核心技术复现。研究聚焦于风能与太阳能发电的波动性特征,结合电解水制氢及氢气合成氨的能量转换环节,构建综合能源系统的多目标优化模型,兼顾经济性、能源利用率与系统稳定性。通过引入先进的优化算法与Cplex等求解工具,对系统关键设备容量进行优化配置,并实现多时段运行调度的精细化决策,推动可再生能源高效转化为绿色化工产品,为“电-氢-氨”一体化系统的设计与运行提供科学依据和技术支撑。; 适合人群:具备一定Python编程能力和优化建模基础,从事新能源系统、氢能利用、综合能源系统规划与运行等方向研究的科研人员、高校研究生及工程技术人员。; 使用场景及目标:①用于风光制氢合成氨系统的容量规划、运行策略制定与经济性评估;②支撑高水平学术论文的模型复现、算法验证与创新研究,提升对多能互补系统协同优化机制的理解与实践能力; 阅读建议:建议结合Cplex等优化求解器运行代码,深入理解模型构建过程中的目标函数设计与约束条件表达,重点关注可再生能源出力不确定性处理与能量转换效率建模,并参考相关文献进一步拓展优化算法与场景分析维度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值