面试中常见现场编程题(手写)

struct ListNode
{
    int value;
    ListNode * next;
    ListNode(int v): value(v),next(NULL){}
}

1链表合并

  合并两个递增排序的链表

ListNode * Merge(ListNode * pHead1,ListNode * pHead2)
{
    if(pHead1==NULL)
        return pHead2;
    else if(pHead2==NULL)
        return pHead1;
    ListNode * pMerge = NULL;
    if(pHead1->value < pHead2->value)
    {
        pMerge = pHead1;
        pMerge->next = Merge(pHead1->next,pHead2);
    }else
    {
        pMerge = pHead2;
        pMerge->next = Merge(pHead1,pHead2->next);
    }
    return pMerge;
}

2 链表相加

  给定两个链表,分别表示两个非负整数。它们的数字逆序存储在链表中,每个结点只存储一个数字,计算两个数字的和,并返回链表头指针

/*不带头结点*/
ListNode * Add(ListNode * head1,ListNode * head2)
{
    ListNode* pSum = NULL;
    ListNode * pTail = NULL;
    ListNode * pCur = NULL;
    int carry = 0;
    int value = 0;
    while(head1 && head2)
    {
        value = carry + head1->value + head2->value;
        carry = value / 10;
        value %= 10;
        pCur = new ListNode(value);
        if(pTail)
        {
            pTail->next = pCur;
            pTail = pCur;
        }else
        {
            pSum = pCur;
            pTail = pCur;
        }
        head1 = head1->next;
        head2 = head2->next;
    }
    ListNode * p = head1 ? head1 : head2;
    while(p)
    {
        value = p->value +carry;
        carry = value / 10;
        value %= 10;
        pCur = new ListNode(value);
        if(pTail)
        {
            pTail->next = pCur;
            pTail = pCur;
        }else
        {
            pSum = pCur;
            pTail = pCur;
        }
        p = p->next;
    }
    if(carry)
    {
        pTail->next = new ListNode(carry);
    }
    return pSum;
}
/*带头结点的情况 */
ListNode * Add(ListNode * head1,ListNode * head2)
{
    ListNode* pSum = new ListNode(0);
    ListNode * pTail = pSum;
        ListNode * p1 = head1->next;
        ListNode * p2 = head2->next;
    ListNode * pCur = NULL;
    int carry = 0;
    int value = 0;
    while(p1&& p2)
    {
        value = carry + p1->value + p2->value;
        carry = value / 10;
        value %= 10;
        pCur = new ListNode(value);
        
        pTail->next = pCur;
        pTail = pCur;
        
        p1= p1->next;
        p2= p2->next;
    }
    ListNode * p = p1? p1: p2;
    while(p)
    {
        value = p->value +carry;
        carry = value / 10;
        value %= 10;
        pCur = new ListNode(value);
    
        pTail->next = pCur;
        pTail = pCur;
        p = p->next;
    }
    if(carry)
    {
        pTail->next = new ListNode(carry);
    }
    return pSum;
}    

3 链表部分翻转

    给定一个链表,翻转该链表从m到n的位置,要求直接翻转而非申请新空间

如 1->2->3->4->5  m=2,n=4  返回 1->4->3->2->5

/*带头结点*/
void Reverse(ListNode * pHead,int from,int to)
{
    ListNode* pCur = pHead->next;
    int i;
    for(i=0;i<from-1;i++)
    {
        pHead = pCur;
        pCur = pCur->next;
    }
    ListNode* pPre = pCur;
    pCur = pCur->pNext;
    to--;
    ListNode * pNext;
    for(;i<to;i++)
    {
        pNext = pCur->pNext;
        pCur->pNext = pHead->pNext;
        pHead->pNext = pCur;
        pPre->pNext = pNext;
        pCur = pNext;
    }
}
/*不用头结点 */
void Reverse(ListNode ** head,int from,int to)
{
    if(head == NULL) return;
    ListNode * pCur = *head;
    ListNode * pHead = *head;
    int i;
    for(i = 0; i < from - 1; i++)
    {
        pHead = pCur;
        pCur = pCur->next;
    }
    ListNode * pPre = pCur;
    pCur = pCur->next;
    ListNode * pNext;
    for(; i < to-1; i++)
    {
        pNext = pCur->next;
        pCur->next = pHead->next;
        pHead->next = pCur;
        pPre->next = pNext;
        pCur = pNext;
    }
}

4 链表划分(思考快排)

  给定一个链表和一个值x,将链表划分为两部门,使得划分后小于x的节点在前,大于x的结点在后,在这两部分中要保持原链表中的出现顺序

/*带头结点*/
void Partition(ListNode * pHead, int pivotkey)
{
    ListNode * pLeft = new ListNode(0);
    ListNode * pRight = new ListNode(0);
    ListNode * left = pLeft;
    ListNode * right = pRight;
    ListNode * p = pHead->next;
    while(p)
    {
        if(p->value < pivotkey)
        {
            left->next = p;
            left = p;
        }else
        {
            right->next = p;
            right = p;
        }
        p = p->next;
    }
    left->next = pRight->next;
    right->next = NULL:
    pHead->next = pLeft->next;
    delete pLeft;
    delete pRight;
}

5 链表环入口

  一个链表中包含环,如何找出环的入口结点

    如图 找到3

ListNode* MeetingNode(ListNode* pHead)
{
    if(pHead == NULL)
        return NULL;

    ListNode* pSlow = pHead->m_pNext;
    if(pSlow == NULL)
        return NULL;

    ListNode* pFast = pSlow->m_pNext;
    while(pFast != NULL && pSlow != NULL)
    {
        if(pFast == pSlow)
            return pFast;

        pSlow = pSlow->m_pNext;

        pFast = pFast->m_pNext;
        if(pFast != NULL)
            pFast = pFast->m_pNext;
    }

    return NULL;
}

ListNode* EntryNodeOfLoop(ListNode* pHead)
{
    ListNode* meetingNode = MeetingNode(pHead);
    if(meetingNode == NULL)
        return NULL;

    // get the number of nodes in loop
    int nodesInLoop = 1;
    ListNode* pNode1 = meetingNode;
    while(pNode1->m_pNext != meetingNode)
    {
        pNode1 = pNode1->m_pNext;
        ++nodesInLoop;
    }

    // move pNode1
    pNode1 = pHead;
    for(int i = 0; i < nodesInLoop; ++i)
        pNode1 = pNode1->m_pNext;

    // move pNode1 and pNode2
    ListNode* pNode2 = pHead;
    while(pNode1 != pNode2)
    {
        pNode1 = pNode1->m_pNext;
        pNode2 = pNode2->m_pNext;
    }

    return pNode1;
}

6 两个链表的第一个公共节点

ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2)
{
    // 得到两个链表的长度
    unsigned int nLength1 = GetListLength(pHead1);
    unsigned int nLength2 = GetListLength(pHead2);
    int nLengthDif = nLength1 - nLength2;
 
    ListNode* pListHeadLong = pHead1;
    ListNode* pListHeadShort = pHead2;
    if(nLength2 > nLength1)
    {
        pListHeadLong = pHead2;
        pListHeadShort = pHead1;
        nLengthDif = nLength2 - nLength1;
    }
 
    // 先在长链表上走几步,再同时在两个链表上遍历
    for(int i = 0; i < nLengthDif; ++ i)
        pListHeadLong = pListHeadLong->m_pNext;
 
    while((pListHeadLong != NULL) && 
        (pListHeadShort != NULL) &&
        (pListHeadLong != pListHeadShort))
    {
        pListHeadLong = pListHeadLong->m_pNext;
        pListHeadShort = pListHeadShort->m_pNext;
    }
 
    // 得到第一个公共结点
    ListNode* pFisrtCommonNode = pListHeadLong;
 
    return pFisrtCommonNode;
}

unsigned int GetListLength(ListNode* pHead)
{
    unsigned int nLength = 0;
    ListNode* pNode = pHead;
    while(pNode != NULL)
    {
        ++ nLength;
        pNode = pNode->m_pNext;
    }
 
    return nLength;
}

7 链表倒数第K个节点

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
    if(pListHead == NULL || k == 0)
        return NULL;

    ListNode *pAhead = pListHead;
    ListNode *pBehind = NULL;

    for(unsigned int i = 0; i < k - 1; ++ i)
    {
        if(pAhead->m_pNext != NULL)
            pAhead = pAhead->m_pNext;
        else
        {
            return NULL;
        }
    }

    pBehind = pListHead;
    while(pAhead->m_pNext != NULL)
    {
        pAhead = pAhead->m_pNext;
        pBehind = pBehind->m_pNext;
    }

    return pBehind;
}

8 删除重复节点

 1->2->3->3->4->4->5     变成  1->2->5

void deleteDuplication(ListNode** pHead)
{
    if(pHead == NULL || *pHead == NULL)
        return;
        
    ListNode* pPreNode = NULL;
    ListNode* pNode = *pHead;
    while(pNode != NULL)
    {
        ListNode *pNext = pNode->m_pNext;
        bool needDelete = false;
        if(pNext != NULL && pNext->m_nValue == pNode->m_nValue)
            needDelete = true;

        if(!needDelete)
        {
            pPreNode = pNode;
            pNode = pNode->m_pNext;
        }
        else
        {
            int value = pNode->m_nValue;    
            ListNode* pToBeDel = pNode;
            while(pToBeDel != NULL && pToBeDel->m_nValue == value)
            {
                pNext = pToBeDel->m_pNext;
                
                delete pToBeDel;
                pToBeDel = NULL;
                
                pToBeDel = pNext;
            }
            
            if(pPreNode == NULL)
                *pHead = pNext;
            else
                pPreNode->m_pNext = pNext;
            pNode = pNext;
        }
    }
}

思考  

8中 保留第一个重复的节点  ?

头插法

链表头结点的作用  思考

原文地址:https://www.cnblogs.com/hlongch/p/5707285.html