关于链表的几个笔试题

一、链表中倒数第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;
        else
			return 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值