链表面试题(四)

【判断单链表是否带环?求环的长度?环的入口点?以及每个算法的时间复杂度和空间复杂度】
【判断两个链表是否相交,求交点?(假设链表不带环)】
关于链表创建和基础的打印问题,在上一篇,戳链接 链表面试题(一)
13,【判断单链表是否带环?求环的长度?环的入口点?】
 单链表带环问题
单链表带环问题,创建俩个指针,一个快指针,一个慢指针,快指针一下走两步,慢指针一下走一步,如果链表带环,最终两个指针会在环中相遇

//时间复杂度O(n),空间复杂度O(1)
SListNode* SListIsCycle(SListNode* list)//单链表带环问题
{
    SListNode* pSlow = list;
    SListNode* pQuick = list;
    while (pQuick != NULL&&pQuick->_next != NULL)
    {
        pQuick = pQuick->_next->_next;//快指针一下走两步
        pSlow = pSlow->_next;//慢指针一下走一步
        if (pSlow == pQuick)//相遇
            return pSlow;//后面算法中出现的meetNode就是这的pSlow相遇的指针
    }
    return NULL;
}

求环的长度
求环的长度问题,从环的相遇点或者环内的一个点开始,一个指针在这等着,另一个指针绕环走一圈,它的步数就是环的长度

////时间复杂度O(n),空间复杂度O(1)
int SListCycleLen(SListNode* meetNode)//求环的长度
{
    SListNode* pCycle = meetNode;//等着的指针
    SListNode* pNext = meetNode->_next;//计步的指针
    int i = 1;
    while (pNext != pCycle)//走到了开始的位置
    {
        pNext = pNext->_next;
        i++;
    }
    return i;
}

 求环的入口点
求环入口点问题,在判断链表带环函数里,有一个相遇点(x),在遇到之前,慢指针走了(L+X),快指针走了(L+nC+X),但是快指针走的步数是慢指针的二倍,那么就能列出图上的算式,解出L=nC+X,那让一个指针从list走,一个从X位置走,他俩相遇的位置就是环的入口点了

//时间复杂度O(n),空间复杂度O(1)
int SListEntryNode(SListNode* list, SListNode* meetNode)//求环的入口点问题
{
    SListNode* plist = list;//链表头结点
    SListNode* pMeetNode = meetNode;//X位置的相遇点
    int i = 1;
    while (plist != pMeetNode)//相遇的位置就是环的入口点
    {
        plist = plist->_next;
        pMeetNode = pMeetNode->_next;
        i++;
    }
    return i;
}

14,【判断两个链表是否相交?求交点?(假设链表不带环)】
判断链表相交
判断链表相交问题,先统计两个链表的长度,并判断两个链表的尾是不是一个尾,如果不是一个尾,那肯定没有相交,用长度大的减去长度小的,那么这时两个链表的长度都是一样的还相交,那么同时从俩链表表头开始往后走,遇到的内个结点就是相交点

int SListIsCrossNode(SListNode* list1, SListNode* list2)//判断链表相交(不带环)
{
    if (list1 == NULL || list2 == NULL)
        return NULL;
    int len1 = 1;
    SListNode* pTail1 = list1;
    while (pTail1->_next != NULL)//统计链表1的长度
    {
        pTail1 = pTail1->_next;
        len1++;
    }
    int len2 = 1;
    SListNode* pTail2 = list2;
    while (pTail2->_next != NULL)//统计链表2的长度
    {
        pTail2 = pTail2->_next;
        len2++;
    }
    if (pTail1 != pTail2)//如果两个链表的尾巴不一样,那么肯定不相交
        return -1;
    SListNode* pNode1 = list1;
    SListNode* pNode2 = list2;
    int k;
    if (len1 > len2)//让俩个指针从相同的位置出发
    {
        k = len1 - len2;
        while (k--)
            pNode1 = pNode1->_next;
    }
    else
    {
        int k = len2 - len1;
        while (k--)
            pNode2 = pNode2->_next;
    }
    k = 1;
    while (pNode1 != pNode2)//相遇的点就是交点
    {
        pNode1 = pNode1->_next;
        pNode2 = pNode2->_next;
        k++;
    }
    return k;
}

如果有不对的地方,可以评论告诉我,望指导!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值