《剑指offer》:[3]得到链表中倒数第K个结点

         由于链表中不能随机得到一个结点的值,也不知道具体的第K个结点在什么位置,不像数组那样随机存取效率高,所以有时候我们需要知道第K个元素的值,这里我们讨论一下如何获得倒数第K个元素的值。
        正向第K个元素很简单,用一趟遍历便可以得到。时间复杂度为O(N)。
       那么倒数第K个元素,还需要遍历一次,其时间复杂度为:O(N)+O(N)=O(N)。遍历一遍,我们就知道了链表的长度N,用一个计数器就搞定。
       那么和倒数第K个元素有什么关系呢?
       倒数第K个元素,也就是正向的第N-K+1个。
       例如:12345,倒数第二个元素4,也就是正向的5-2+1=4。

       所以基于这个原理我们可以很快的得到解决方案一:遍历两次,第二次得到第N-K+1的位置。但是第一种方案遍历了两次链表,有时候我们要求只遍历一次。

       那么又有了第二种方案。

          方案二:这也是受第一种方案的启发。因为链表的总长度N不变,借助两个指针,一个向前走K-1步后,第二个指针开始从头走,当第一个走到尾结点的时候,第二个指针走了N-K+1步,和第一种方案原理类似。但是我们只遍历了一次,提高了效率。
        方案一的代码是实现比较简单,省略。这里主要是实现方案二:

        具体代码如下:

#include <iostream>
using namespace std;
struct List
{
	int number;
	List *pNext;
};
List *pHead=NULL;
List *pEnd=NULL;
List *pNode=NULL;
void CreateList()
{
	int number;
	cout<<"please input the number:"<<endl;
	cin>>number;
	while(0!=number)
	{
		pNode=new List;
		pNode->number=number;
		pNode->pNext=NULL;
		if(NULL==pHead)
		{
			pHead=pNode;
			pEnd=pNode;
		}
		else
		{
			pEnd->pNext=pNode;
			pEnd=pNode;
		}
		cin>>number;
	}
}
void show()
{
	List *temp=pHead;
	cout<<"List:";
	while(temp)
	{
		cout<<temp->number<<" ";
		temp=temp->pNext;
	}
	cout<<endl;
}
List* Backword_K(int num)
{
	List *First=pHead;
	List *second=pHead;
	//输入的K不符合要求,小于等于0;链表为NULL;
	if(!pHead || 0==num)
		return NULL;
	//K大于链表的长度的情况;
	for(int i=0;i<num-1;i++)
	{
		if(First->pNext!=NULL)
		{
			First=First->pNext;
		}
		else
		{
			return NULL;
		}
	}
	while(First->pNext)
	{
		First=First->pNext;
		second=second->pNext;
	}
	return second;
}
int main()
{
	int position=3;
	int result=0;
	CreateList();
	show();
	List *temp=Backword_K(position);
    result=temp->number;
	cout<<"倒数第"<<position<<"个数是:"<<result<<endl;
	system("pause");
	return 0;
}
运行结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值