leetCode160--相交链表(C语言版)

题目

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

思路设计

首先明确一点: 判断两个链表是否相交的条件是 判断相关两个节点的地址是否相同,不是节点存储的值是否相同

方法一 暴力遍历

用一个链表的每一个节点去匹配另一个链表的节点,当两个节点的地址相同时,此节点就是相交节点。大家有兴趣的可以试试。

方法二

因为两个链表的公共部分长度一样,但非公共部分一般是不一样的,如果我们能屏蔽掉非公共部分的长度影响,那么就可以直接使用一个for循环同时对两个链表进行遍历来寻找相交节点了。

屏蔽长度差影响方法一
  1. 先求出两个链表的长度,再求出长度差值dis。
  2. 让一个指针P1先从较长链表的头节点出发,走长度差值dis个节点,这样就屏蔽掉了链表之间的长度插;然后与从短链表头节点的另一个指针P2同时开始遍历各自对应链表,每到一个节点就互相判断地址是否相同。
上代码
/**
* 求链表长度
*/
int getLength(struct ListNode *list)
{
    int length = 0;
    while (list)
    {
        length++;
        list = list->next;
    }
    return length;
}

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
    if (!headA || !headB) //任一链表为空则不存在相交可能
    {
        return NULL;
    }

   struct ListNode *nodeA = headA;
    struct ListNode *nodeB = headB;
    int lengthOfListA = getLength(nodeA);
    int lengthOfListB = getLength(nodeB);
    int dis = (lengthOfListA < lengthOfListB) ? (lengthOfListB-lengthOfListA) : (lengthOfListA - lengthOfListB); //链表长度差

    if (lengthOfListA > lengthOfListB) //找到较长链表,让其指针先走差值dis个节点
    {
        for (int i = 0; i < dis; i++)
        {
            nodeA = nodeA->next;
        }
    }
    else
    {
        for (int i = 0; i < dis; i++)
        {
            nodeB = nodeB->next;
        }
    }
    while (nodeA != nodeB) // 屏蔽掉长度差后,同步遍历两个链表,找到相交节点后跳出循环;若没有相交节点,nodeA取值为null
    {
        nodeA = nodeA->next;
        nodeB = nodeB->next;
    }
    return nodeA;
}

复杂度分析

时间复杂度

for循环执行了dis次,然后while循环K次,总的执行次数肯定小于等于长链表长度,所以时间复杂度就取O(n)

空间复杂度

我们只使用了两个指针,所以空间复杂度为O(1)

屏蔽长度差影响方法二
  1. 让短链表指针P1、长链表指针P2同时从各自表头遍历
  2. 当短链表指针遍历完短链表后接着遍历长链表,长链表指针遍历完自己后接着遍历短链表,当两个指针所指节点地址一样时,这个节点就是相交节点。
    为方便解释我就引用大佬的图(原图地址就在leetCode 160题题解评论区):
    图一
    图二
上代码
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
    if (!headA || !headB) 
    {
        return NULL;
    }

    struct ListNode *nodeA = headA;
    struct ListNode *nodeB = headB;
    while (nodeA != nodeB) //没有找到相交节点前
    {
        nodeA = nodeA == NULL ? headB:nodeA->next; //A链表没有遍历完就一直遍历,如果遍历完就接着从B链表遍历
        nodeB = nodeB == NULL ? headB:nodeB->next; // B同上,当两个节点地址相同时结束循环
    }
    return nodeA;
}

复杂度分析

时间复杂度

只使用了while循环,执行次数是链表长度的常数倍,所以时间复杂度还是O(n)

空间复杂度

我们只使用了两个指针,所以空间复杂度为O(1)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值