单链表面试题——进阶篇

来源:互联网 发布:beyond compare mac版 编辑:程序博客网 时间:2024/06/05 09:19

1.判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法的时间复杂度&空间复杂度。
判断是否带环:利用快慢指针,快指针每次走两步,慢指针每次走一步,如果快慢指针相遇,则该链表带环。

ListNode* IsHaveLoop(ListNode* plist){    if (plist == NULL)    {        return NULL;    }    ListNode* fast = plist;    ListNode* slow = plist;    while (fast->next&&fast)    {        fast = fast->next->next;        slow = slow->next;        if (fast == slow)        {            return slow;        }    }    return NULL;}

求环的长度:相遇之后,每次追一步,再次相遇刚好追一圈——环的长度。

int SizeofLoop(ListNode* plist)//求环长{    ListNode* meet = IsHaveLoop(plist);    if (meet)    {        int count = 1;        ListNode* tmp = meet->next;        while (tmp != meet)        {            tmp = tmp->next;            count++;        }        return count;    }    return 0;}

求环入口点: T——尾长(非环长度),S——慢指针入环到被追上, C——快指针追慢指针多跑的圈。那么,慢指针走的路程为 T+S,快指针走的路程为 T+S+C,可得 2(T+S)=T+S+C,T=C-S,此时,一个指针从起点出发走T步,一个指针从快慢指针相遇点出发走 C-S 步,此时两指针刚好都在入口点。

ListNode* EnterNode(ListNode* plist) {    ListNode* meet = IsHaveLoop(plist);    if(meet)    {        while (meet != plist)        {            meet = meet->next;            plist = plist->next;        }        return plist;    }    return NULL;}

2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)

ListNode* Intersect(ListNode* pList1, ListNode* pList2){    int count1 = 0, count2 = 0;    ListNode* p1 = pList1, *p2 = pList2;    while (p1->next)    {        count1++;        p1 = p1->next;    }    while (p2->next)    {        count2++;        p2 = p2->next;    }    if (p1 != p2)    return NULL;    if (count1 >= count2)    {        count1 -= count2;        while (count1--)            pList1 = pList1->next;        while (pList1 != pList2)        {            pList1 = pList1->next;            pList2 = pList2->next;        }        return pList1;    }    else    {        count2 -= count1;        while (count2--)            pList2 = pList2->next;        while (pList1 != pList2)        {            pList1 = pList1->next;            pList2 = pList2->next;        }        return pList1;    }}

3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
这里写图片描述

ListNode* Intersect(ListNode* plist1, ListNode* plist2)//判断链表是否相交升级版{    //先判断是否为空    if ((plist1 == NULL) || (plist2 == NULL))    {        return NULL;    }    ListNode* enter1 = EnterNode(plist1);    ListNode* enter2 = EnterNode(plist2);    //1和2:若两个链表都无环,则直接用题目二的函数解决    if ((enter1 == NULL) && (enter2 == NULL))    {        return IsListIntersect(plist1, plist2);    }        //4:若一个有环,一个无环,则不想交,返回NULL       else if ((enter1 == NULL) && (enter2 != NULL) || (enter1 != NULL) && (enter2 == NULL))    {        return NULL;    }    //3: 若入口点相同都在尾巴,去掉环,转化成无环相交问题    else if (enter1 == enter2)    {        enter1->next = NULL;        enter2->next = NULL;        return IsListIntersect(plist1, plist2);    }    //6 :同环,两个入口点  一个入口点开始遍历一圈,看环上是否有另一个入口点          // 找到则返回plist1的入口点      else    {        ListNode* tmp = enter1->next;        while (tmp != enter1)        {            if (tmp == enter2)            {                return enter1;            }            tmp = tmp->next;        }        return NULL;    }}

4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。

这里写图片描述
这里写图片描述
这里写图片描述

ComplexNode* CopyList(ComplexNode* plist){    if (plist == NULL)    {        return NULL;    }    ComplexNode* newnode = NULL;    ComplexNode* tmp = plist;    //1.1 插入节点    while (tmp != NULL)    {        newnode = (ComplexNode*)malloc(sizeof(ComplexNode));        newnode->_data = tmp->_data;        newnode->_next = tmp->_next;        newnode->_random = NULL;        tmp->_next = newnode;        tmp = tmp->_next->_next;    }    //1.2开始连接random    tmp = plist;    newnode = plist->_next;    while (tmp != NULL)    {        if (tmp->_random != NULL)        {            newnode->_random = tmp->_random->_next;        }        tmp = tmp->_next->_next;        if (tmp)        {            newnode = tmp->_next;        }    }    //2.分离两个链表    ComplexNode* res = plist->_next;    tmp = plist;    tmp->_next = tmp->_next->_next;    tmp = tmp->_next;    newnode = plist->_next;    while ((tmp->_next != NULL)&&(tmp != NULL))    {        newnode->_next = newnode->_next->_next;        tmp->_next = tmp->_next->_next;        tmp = tmp->_next;        newnode = newnode->_next;    }    return res;}
原创粉丝点击