26、【链表】相交链表(C++版本)

题目描述

在这里插入图片描述在这里插入图片描述

题目分析

目标是找到两个链表若相交时的公共结点,那么便需要分析公共结点所具有的特性。

假设链表A和链表B具有公共结点,那么在公共结点处之后,两个链表具有相同长度和数值的结点。而在公共结点之前,两个链表的所具有的结点个数并不一定相等。

因此,若分别从链表A和B的公共结点开始遍历直到遍历到NULL结束,则链表A和链表B的遍历次数一定相等。问题的关键便是如何找到这一部分相等的长度,影响我们无法找到长度的因素是链表A和B公共节点之前的链表,因为公共结点之前的链表长度不一定相等。

因此,我们从链表的长度进行研究。
设链表A的长度为:
a + x = la
其中a为公共结点之前的链表长度,x为从公共结点到最后一个结点的长度,la为链表A的总长度。

设链表B的长度为:
b + x = lb
其中b为公共结点之前的链表长度,x为从公共结点到最后一个结点的长度,lb为链表B的总长度。

而我们可发现a + b + x = la + b = lb + a,根据这一条件,便可以找到等价关系,便找到了边界条件。

所以,la + b = lb + a,即走完A后再走B的前一段距离等于走完B后再走A的前一段距离。
在这里插入图片描述

参考文章:
图解相交链表

Intersection of Two Linked Lists (双指针,链表拼接)

代码实现

分别定义一个指针cur_a指向headA和指针cur_b指向headB,当cur_a遍历完headA时,让它指向headB的开头,同理,让cur_b遍历完时,让它指向headA的开头。目的是让两个指针分别走过上述a + b + x长度的路程,从而消除两个链表之间的长度差。当消除完后,两个链表的下一个结点,便是公共结点。

当走完后,如果为NULL,则说明无公共结点,否则返回的便是公共结点。

class Solution {
public:
	ListNode *getIntersectionNode(ListNode *headA, ListNode *headB){
	if(headA == nullptr && headB == nullptr)
		return nullptr;
	ListNode* cur_a = headA;
	ListNode* cur_b = headB;

	while(cur_a != cur_b)	{
		cur_a = (cur_a ? cur_a->next : headB);
		cur_b = (cur_b ? cur_b->next : headA);
	}
	return cur_a;
}
};
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        p1, p2 = headA, headB

        while p1 != p2 :
            p1 = p1.next if p1 else headB
            p2 = p2.next if p2 else headA
        
        return p1

时间复杂度为O(n),空间复杂度为O(n)

链表相交

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
你好,下面是用C++创建两个相交链表的示例代码: ```c++ #include <iostream> using namespace std; // 定义链表节点 struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; // 创建两个相交链表 ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { ListNode *p1 = headA, *p2 = headB; while (p1 != p2) { // 遍历到链表末尾后,从另外一个链表头部继续遍历 p1 = p1 == nullptr ? headB : p1->next; p2 = p2 == nullptr ? headA : p2->next; } return p1; } int main() { // 创建第一个链表 ListNode *headA = new ListNode(1); ListNode *n1 = new ListNode(2); ListNode *n2 = new ListNode(3); ListNode *n3 = new ListNode(4); headA->next = n1; n1->next = n2; n2->next = n3; // 创建第二个链表 ListNode *headB = new ListNode(5); ListNode *m1 = new ListNode(6); ListNode *m2 = new ListNode(7); ListNode *m3 = n2; // 第二个链表从第一个链表的第三个节点开始相交 headB->next = m1; m1->next = m2; m2->next = m3; // 遍历两个链表验证相交 ListNode *intersectionNode = getIntersectionNode(headA, headB); if (intersectionNode != nullptr) { cout << "链表相交点为:" << intersectionNode->val << endl; } else { cout << "链表相交" << endl; } return 0; } ``` 输出结果: ``` 链表相交点为:3 ``` 在这个例子中,我们创建了两个相交链表,然后通过 `getIntersectionNode` 函数遍历两个链表,找到它们的相交点,并返回相交点的指针。在主函数中,我们输出了相交点的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辰阳星宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值