1. 程式人生 > >【資料結構】連結串列面試題升級版

【資料結構】連結串列面試題升級版

1、複雜連結串列的複製

複雜連結串列
一個連結串列的每個結點,有一個next指標指向下一個結點,還有一個random指標指向這個連結串列中的隨機一個結點或者NULL。
現在要求複製這個連結串列,並返回複製後的新連結串列。
思路如下:
在這裡插入圖片描述
複雜連結串列的資料型別:

typedef struct ComplexNode
{
    int data;
    ComplexNode *next;
    ComplexNode *random;
}ComplexNode;

程式碼如下:

//建立一個新結點
ComplexNode *CreateComNode(int data)
{
    ComplexNode *newNode = (ComplexNode *)malloc(sizeof(ComplexNode));
    newNode->data = data;
    newNode->next = NULL;
    newNode->random = NULL;
    return newNode;
}
ComplexNode *CopyComplexList(ComplexNode **pFirst)
{
    ComplexNode *newNode = NULL;
    ComplexNode *cur = NULL;
    //1.複製每個結點,讓新結點跟在老結點後面
    cur = *pFirst;
    while(cur != NULL)
    {
        newNode = CreateComNode(cur->data);
        newNode->next = cur->next;
        cur->next = newNode;
        cur = newNode->next;
    }
    //2、複製random
    cur = *pFirst;
    while(cur != NULL)
    {
        newNode = cur->next;
        if(cur->random != NULL)
        {
            newNode->random = cur->random->next;
        }
        cur = newNode->next;
    }
    //3、把一個連結串列拆成兩個連結串列
    ComplexNode *newNext = NULL;
    ComplexNode *next = NULL;
    ComplexNode *result = NULL;
    int flag = 1;
    cur = *pFirst;
    while(cur != NULL)
    {
        newNode = cur->next;
        if(flag)
        {
            result = newNode;
            flag = 0;
        }
        next = newNode->next;
        if(next == NULL)
        {
            newNext = NULL;
        } 
        else
        {
            newNext = next->next;
        }
        cur->next = next;
        newNode->next = newNext;
        cur = next;
    }
    return result;
}

2、判斷兩個連結串列是否相交,若相交,求交點(假設連結串列不帶環)

思路如下:
在這裡插入圖片描述
程式碼如下:

//計算連結串列長度
int GetListLen(ListNode *p)
{
    int count = 0;
    ListNode *cur = p;
    while(cur != NULL)
    {
       count++;
       cur = cur->next;
    }
    return count;
}
//判斷兩條連結串列是否相交,若相交,返回交點
ListNode *IsIntersect(ListNode *p1, ListNode *p2)
{
     ListNode *cur1 = p1;
     ListNode *cur2 = p2;
     int len1 = 0;
     int len2 = 0;
     int ret = 0;
     while(cur1 != NULL)
     {
         cur1 = cur1->next;
     }
     while(cur2 = cur2->next)
     {
         cur2 = cur2->next;
     }
     if(cur1 == cur2)//如果條件成立,說明相交
     {
         cur1 = p1;
         cur2 = p2;
         len1 = GetListLen(p1);
         len2 = GetListLen(p2);
        if(len1>len2)
        {
           ret = len1-len2;
           while(ret--)
           {
                cur1 = cur1->next;
           }
        }
        else if(len1<len2)
        {
           ret = len2-len1;
           while(ret--)
           {
                cur2 = cur2->next;
           }
        }
        while(cur1 != cur2)
        {
            cur1 = cur1->next;
            cur2 = cur2->next;
        }
        return cur1; //找到交點
     }
     else
         return NULL;
}

3、判斷單鏈表是否帶環?若帶環,求環的長度?求環的入口點?

思路如下:
在這裡插入圖片描述程式碼如下:

//判斷是否帶環,帶環返回快慢指標相遇結點
ListNode *IsCircleList(ListNode *p)
{
    int count = 0;
    ListNode *fast = p;
    ListNode *slow = p;
    while(fast != NULL)
    {
        fast = fast->next;
        count++;
        if(count%2==0)
        {
            slow = slow->next;
        }
        if(fast == NULL)
        {
            break;
        }
        if(fast == slow)
        {
            return fast;
        }
    }
    return NULL;
}
//求環的長度
int LenOfCircle(ListNode *p)
{
    int count = 0;
    ListNode *cur = NULL;
    ListNode *NodeInCircle = NULL;
    //從頭遍歷連結串列,找到相遇點
    NodeInCircle = IsCircleList(p);
    cur = p;
    while(cur != NodeInCircle)
    {
        cur = cur->next;
    }
    while(cur->next != NodeInCircle)
    {
        cur = cur->next;
        count++;
    }
    count++;
    return count;
}
//求環的入口點
ListNode *EntryNode(ListNode *p)
{
    ListNode *dot = NULL;
    ListNode *ret = NULL;
    ListNode *cur = NULL;
    ListNode *NodeInCircle = NULL;
    //從頭遍歷連結串列,找到相遇點
    NodeInCircle = IsCircleList(p);
    cur = p;
    //找出相遇點的前一個結點,將它置為空指標,相當於從相遇點斷開環
    //然後以兩條連結串列相交的角度找入口點,兩條連結串列相交處就是環的入口點
    while(cur->next != NodeInCircle)
    {
        cur = cur->next;
    }
    dot = cur;
    cur->next = NULL;
    cur = NodeInCircle;
    ret = p;
    while(cur != ret)
    {
        cur = cur->next;
        ret = ret->next;
    }
    dot->next = NodeInCircle;
    return cur;
}

4、判斷兩個連結串列是否相交,若相交,求交點(假設連結串列帶環)【升級版】

思路如下:
在這裡插入圖片描述