算法修炼之路——【链表】Leetcode 160 相交链表

题目描述

编写一个程序,找到两个单链表相交的起始节点。

如示例1:

输入: listA = [1, 1, 2, 3, 4, 5]; listB = [1, 2, 3, 4, 5]
输出: ListNode(3)
在这里插入图片描述
图1

注意:

  • 如果两个链表没有交点,返回null;
  • 在返回结果后,两个链表仍须保持原有的结构;
  • 可假定整个链表结构中没有循环;
  • 程序尽量满足O(N)时间复杂度,且仅用O(1)内存。

思路分析

第一次看到这道题目时,很容易想到Leetcode142,不同的是它们是一个链表且内部可能带有循环,求解循环的初始节点,我们可以通过Leetcode142来类似思考。

为方便讲解,我们直接按照图1所给的图示进行推理,说明中已经给出希望使用常量级的空间,则不能借助辅助容器,所以我们直接思考指针解法。这里假设,两个指针,第一个命名为pA,起始节点为listA头节点; 第二个名命为pB, 起始节点为listB头节点。根据Leetcode142我们知道,当两个指针相遇时,其必走过了相同个数的节点,这时我们就知道了结果判定条件,即pA == pB,这样我们再进一步的往前推进。

这里给出的两条链表,当我们的指针运行到各自链表尾部的时候,该如何处理?题目中没有给出两条链表的长度大小信息,再根据之前我们的经验判定:走过了相同个数的节点,则不妨当pA指向listA尾节点时,下一步将其指向listB的头节点;类似地,pB指向listB尾节点时,下一步将其指向listA的头节点。这样我们易知,当存在两个链表地交点时,一定会有pA == pB && pA != null的满足节点存在,此时,pA即我们的返回节点。

边界条件考虑

这里,我们在思路分析中给出了一般规则,但是更重要的是边界问题的统一化,这里我们需要进一步测试以下边界问题:

  1. 当两个链表不存在相交节点时,此时的处理规则是什么?
  2. 能否将边界条件的解决统一到一般规则内?

对于问题1,我们来细致的讨论。当两条链表不存在交点时,即图2所示的情况:
在这里插入图片描述
图2

我们先按照一般规则判断会不会发生异常:

代码1:

ListNode pA = listA;
ListNode pB = listB;

while(pA != pB){
	pA = pA.next;
	pB = pB.next;
}

return pA;

while循环体运行第5次的时候,此时pA -> ListNode(5), pB -> null; 此时依然满足pA != pB,故进入第6次循环,则有pA -> null, pB -> null,此时循环终值,返回值pA = null,返回正确,即一般规则覆盖了此边界情况。

对于问题2,当两条链表存在交点时,尤其是两条链表不等时,我们每个指针至少均对两条链表遍历近一次后,会发现节点;此时我们需要在循环体内,给出连接到另一个链表头的代码,将代码1改善后,则有:

ListNode pA = listA;
ListNode pB = listB;

while(pA != pB){
	pA = pA == null ? listB : pA.next;;
	pB = pB == null ? listA : pB.next;
}

return pA;

到此,我们已经讨论了一般规则与边界情况,此时可直接给出代码如下:

解题代码

    public static ListNode solution(ListNode listA, ListNode listB) {
        if (listA == null || listB== null ) {
            return null;
        }

        
        ListNode pA = listA;
        ListNode pB = listB;  
        
        while(pA != pB ){
            pA = pA == null ? listB : pA.next;
            pB = pB == null ? listA : pB.next;
        }
        
        return pA;
    }

特别说明

这里的解题代码书写方式是参照网络大神解法,但因难以溯源,且分析过程为原创,故此篇文章标为“原创”,望请谅解。

复杂度分析

时间复杂度:我们对数据遍历次数小于等于两次,时间复杂度为O(N);
空间复杂度:我们没有借助额外的容器,所以空间复杂度为常量级O(1)。

GitHub源码

完整可运行文件请访问GitHub

发布了47 篇原创文章 · 获赞 55 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u011106767/article/details/105427576