链表笔试面试题(一)


本博客内容

1、单链表的结构
2、求链表的长度
3、单链表反转
4、单链表倒数第k个节点
5、查找链表的中间节点
6、从尾到头打印链表
7、已知2个单链表有序,把它们合并为一个有序链表
8、判断一个单链表是否有环
9、判断2个链表是否相交
10、求2个单链表相交的第1个节点

1、单链表的结构

struct ListNode
{
    int m_nValue;
    ListNode * m_pNext;
};

2、求链表的长度

unsigned int GetListLength(ListNode * pHead)</font>
{
    if(pHead==NULL)
        return 0;
    ListNode * pNode=pHead;
    unsigned int length=0;
    while(pNode)
    {
    length++;
    pNode=pNode->m_pNext;
    }
    return length;
}   

3、单链表反转

① 采用交换的方法

ListNode * ReverseList(ListNode * pHead)
{
    if(!pHead||!pHead->m_pNext)
        return pHead;
    ListNode * pReverseHead=NULL;
    ListNode * pNode=pHead;
    ListNode * pPrev=NULL;
    while(pNode)
    {
        ListNode * pNext=pNode->m_pNext;
        if(!pNext)
            pReverseHead=pNode;
        pNode->m_pNext=pPrev;
        pPrev=pNode;
        pNode=pNext;
    }
    return pReverseHead;

②递归方法

ListNode * ReverseList(ListNode * pHead)
{
    if(!pHead||!pHead->m_pNext)
        return pHead;
    ListNode * result=ReverseList(pHead->m_pNext);
    pHead->m_pNext->m_pNext=pHead;
    pHead->m_pNext=NULL;
    return result;
}

③使用辅助栈空间

ListNode * ReverseList(ListNode * pHead)
{
    if(!pHead||!pHead->m_pNext)
        return pHead;
    stack<ListNode * > stk;
    ListNode * pNode=pHead;
    while(pNode->m_pNext)
    {
        stk.push(pNode);
        pNode=pNode->m_pNext;
    }
    //此时pNode指向最后一个节点
    ListNode * result=pNode;
    while(!stk.empty())
    {
        pNode->m_pNext=stk.top();
        pNode=pNode->m_pNext;
        stk.pop();
    }
    pNode->m_pNext=NULL;
    return result;
}

4、单链表倒数第k个节点

ListNode * GetLastKNode(ListNode *pHead,unsigned int k)
{
    if(!pHead||k<=0)
        return NULL;
    ListNode * pNode=pHead;
    //快指针先走k-1步
    unsigned int length=0;
    while(pNode)
    {
        length++;
        pNode=pNode->m_pNext;
    }
    if(k>length)
        return NULL;  //此处对k进行最大值判断
    ListNode * fastList=pHead;
    ListNode * slowList=pHead;
    while(--k>0)
    {
        if(fastList->m_pNext)    //需要判断是否存在下一个节点
            fastList=fastList->m_pNext;
        else
            return NULL;
    }
    while(!fastList->m_pNext)
    {
        fastList=fastList->m_pNext;
        slowList=slowList->m_pNext;
    }
    return slowList;
}

5、查找链表的中间节点

//原理,和倒数第k个节点一样,采用快慢指针
ListNode * GetMiddleNode(ListNode * pHead)
{
    if(pHead==NULL||pHead->m_pNext==NULL)
        return pHead;
    ListNode * pAhead=pHead;
    ListNode * pBehind=pHead;
    while(pAhead->m_pNext!=NULL)
    {
        pAhead=pAhead->m_pNext;
        pBehind=pBehind->m_pNext;
        if(pAhead->m_pNext)   //此处需要判断快指针是否有后续节点
            pAhead=pAhead->m_pNext;
    }
    return pBehind;
}

6、从尾到头打印链表

①辅助栈

void PrintList(ListNode * pHead)
{
    if(pHead==NULL)
        return ;
    stack<ListNode * > stk;
    ListNode * pNode=pHead;
    while(pNode)
    {
        stk.push(pNode);
        pNode=pNode->m_pNext;
    }
    while(!stk.empty())
    {
            printf("%d\t",stk.top()->m_nValue);
            stk.pop();
    }
}

②递归

void PrintList(ListNode * pHead)
{
    if(pHead==NULL)
        return ;
    else
        {
            PrintList(pHead->m_pNext);
            printf("%d\t",pHead->m_nValue);
        }
}       

7、已知2个单链表有序,把它们合并为一个有序链表

①递归

//递归操作相对简单
ListNode * MergeList(ListNode * pHead1,ListNode * pHead2)
{
    if(!pHead1) return pHead2;
    if(!pHead2) return pHead1;
    ListNode * result=NULL;
    if(pHead1->m_nValue<=pHead2->m_nValue)
        {
            result=pHead1;
            result->m_pNext=MergeList(pHead1->m_pNext,pHead2);
        }
    else
        {
            result=pHead2;
            result->m_pNext=MergeList(pHead1,pHead2->m_pNext);
        }
    return result;
}   

②循环

ListNode * MergeList(ListNode * pHead1,ListNode * pHead2)
{
    if(pHead1==NULL) return pHead2;
    if(pHead2==NULL) return pHead1;
    ListNode * pHeadMerged=NULL;
    if(pHead1->m_nValue<pHead2->m_nValue)//先确定链表头部
    {
        pHeadMerged=pHead1;
        pHeadMerged->m_pNext=NULL;
        pHead1=pHead1->m_pNext;
    }
    else
    {
        pHeadMerged=pHead2;
        pHeadMerged->m_pNext=NULL;
        pHead2=pHead2->m_pNext;
    }
    ListNode * pTemp=pHeadMerged;
    while(pHead1!=NULL&&pHead2!=NULL)
    {
        if(pHead1->m_nValue<pHead2->m_nValue)
        {
            pTemp->m_pNext=pHead1;
            pHead1=pHead1->m_pNext;
            pTemp=pTemp->m_pNext;
            pTemp->m_pNext=NULL;
        }
        else
        {
            pTemp->m_pNext=pHead2;
            pHead2=pHead2->m_pNext;
            pTemp=pTemp->m_pNext;
            pTemp->m_pNext=NULL;
        }
    }
        if(pHead1!=NULL)
            pTemp->m_pNext=pHead1;
        else if(pHead2!=NULL)
            pTemp->m_pNext=pHead2;
        return pHeadMerged;
}

8、判断一个单链表是否有环

bool HasCircle(ListNode * pHead)
{
    ListNode * pFast=pHead;
    ListNode * pSlow=pHead;
    while(pFast||pFast->m_pNext)  //需要有条件判断
    {
        pFast=pFast->m_pNext->m_pNext;
        pSlow=pSlow->m_pNext;
        if(pSlow==pFast)
            return true;
    }
    return false;
}       

9、判断2个链表是否相交

//思路:如果2个链表相交,则它们最后一个节点肯定相同
bool IsInterseted(ListNode * pHead1,ListNode * pHead2)
{
    if(pHead1==NULL || pHead2==NULL)
        return false;
    ListNode * pTail1=pHead1;
    while(pTail1->m_pNext!=NULL)
        pTail1=pTail1->m_pNext;
    ListNode * pTail2=pHead2;
    while(pTail2->m_pNext!=NULL)
        pTail2=pTail2->m_pNext;
    return pTail1==pTail2;
}

10、求2个单链表相交的第1个节点

ListNode * FindFirstCommonNode(ListNode * pHead1,ListNode * pHead2)
{
    int len1=GetListLength(pHead1);
    int len2=GetListLength(pHead2);
    ListNode * longList=pHead1;
    ListNode * shortList=pHead2;
    int dis=len1-len2;
    if(dis<0)
    {
        dis=len2-len1;
        longList=pHead2;
        shortList=pHead1;
    }
    while(dis>0)
    {
        longList=longList->m_pNext; //长链表先向后走dis步
        dis--;
    }
    //然后2个链表指针一起向后走
    while(longList&&shortList&&longList!=shortList)
    {
        longList=longList->m_pNext;
        shortList=shortList->m_pNext;
    }
ListNode * result=longList;
    return result;
}

欢迎转载,请注明出处,欢迎批评指正,谢谢~.未完待续…

猜你喜欢

转载自blog.csdn.net/xiongluo0628/article/details/81352918
今日推荐