关于链表的几个笔试题

来源:互联网 发布:steam怎么下载软件 编辑:程序博客网 时间:2024/06/07 00:34

一、链表中倒数第K个节点

方法一:假设整个链表有n个结点,那么倒数第K个结点就是从头结点开始的第n-k+1个结点。因此通过遍历链表获得结点数n,然后从头结点开始往后走n-k+1步就可以了。但是这种方法需要遍历两次链表。

//方法一struct ListNode{int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};ListNode* FindKthToTail(ListNode* pListHead, unsigned int k){if(pListHead==NULL||k<=0)return NULL;    ListNode* pAhead=pListHead;    ListNode* pBhead=pListHead;    int n=0;    while(pAhead->next!=NULL)    {pAhead=pAhead->next;        n++;    }    for(unsigned int i=0;i<n-k+1;i++)    {if(pBhead->next!=NULL)pBhead=pBhead->next;        elsereturn NULL;    }    return pBhead;}  
方法二:定义两个指针都指向链表头,第一个指针从链表头的头指针开始遍历向前走k-1,第二指针保存不动;从第k步开始,第二个指针也开始从链表的头指针开始遍历。由于两个节点的距离保存在k-1,当第一个指针达到链表的尾结点时,第一个结点正好是倒数第k个节点。如下图所示:


在有6个节点的链表中找倒数第3个节点的过程(a)P1先走两步 

(b)P1走了两步后,P2指向链表头(c)两指针一同向前走,当P1指向链尾时,P2指向即为所求位置

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k){if(pListHead==NULL||k<=0)return NULL;    ListNode* pAhead=pListHead;    ListNode* pBhead=pListHead;    for(unsigned int i=0;i<k-1;i++)    {        if(pAhead->next!=NULL)    pAhead=pAhead->next;        else            return NULL;    }    while(pAhead->next!=NULL)    {        pAhead=pAhead->next;        pBhead=pBhead->next;    }    return pBhead;}
提高代码的鲁棒性,需要考虑的问题:a、输入pListhead为空,输入参数K小于等于0;b、输入参数K大于链表结点数n
二、反转链表

题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点,链表结点

struct ListNode{int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};
为完成反转,序定义3个指针,分别指向当前遍历到的结点、它的前一个结点及后一个结点(以防止链表断开)。图解如下:

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



0 0
原创粉丝点击