算法题:求链表倒数第K个结点

说明:本文仅供学习交流,转载请标明出处,欢迎转载!

       题目:给出一个单链表,返回倒数第K个结点,最后一个结点为倒数第1个

     《剑指offer》上面给的解法是设置两个指针,这里记为p1、p2,先让p2走(k-1)步,然后p1、p2同时走,当p2走到最后一个结点时,p1所指向的结点就是倒数第k个结点。

         我觉得按照这样的逻辑写代码反而更容易出错,因为我们需要把我两件重要的问题:(1).p2先走(k-1)步;(2)循环结束的条件是p2到达最后一个结点,即p2->next==NULL。显然这样不太容易控制,我的想法是先让p2先走k步,然后p1,p2一块走,循环结束的条件是p2到达NULL,即p2==NULL,这样比较直观

         我们用Node *FindLastK(Node *head,int k)表示求解函数,同时在要注意以下特殊情况:

       (1)处理空链表的情况,即head=NULL的情况;

       (2)处理k<1的情况;(注意k从1开始)

       (3)处理链表长度小于k的情况。

         代码如下:

#include<iostream>
using namespace std;
struct Node
{
	int value;
	Node* next;
	Node(int v):value(v){}
};
/*创建一个链表,1->2->3->4->5->6->7*/
Node* CreateList()//创建一个单链表
{
   Node *head;
   Node *n1=new Node(1);
   Node *n2=new Node(2);
   Node *n3=new Node(3);
   Node *n4=new Node(4);
   Node *n5=new Node(5);
   Node *n6=new Node(6);
   Node *n7=new Node(7);
   head=n1;
   n1->next=n2;
   n2->next=n3;
   n3->next=n4;
   n4->next=n5;
   n5->next=n6;
   n6->next=n7;
   n7->next=NULL;
   return head;
}
void FreeList(Node *head)//将链表空间释放
{
	if(head==NULL)
	{
		return ;
	}
	else
	{
		Node *temp=head->next;
		delete head;
		head=temp;
		FreeList(head);
	}
}
void VisitList(Node *head)//遍历链表中的元素,用递归的方法遍历
{
	if(head)
	{
		cout<<head->value<<"->";
		VisitList(head->next);
	}
	else
	{
		cout<<"null"<<endl;
	}
}
Node *FindLastK(Node *head,int k)//查找倒数第K个元素,最后一个元素时倒数第一个
{
	if(head==NULL || k<1)
	{
		return NULL;
	}
	else
	{
		Node *pre,*p;
		pre=p=head;
		int i;
		for(i=0;p && i<k;i++)//要保证p存在,p先走k步
		{
			p=p->next;
		}
		if(i<k)//说明没走到k步,即k大于链表的长度
		{
			return NULL;
		}
		else//如果一切正常,则两者同时走
		{
			while(p)
			{
				p=p->next;
				pre=pre->next;
			}
		}
		return pre;
	}
}
int main()
{
	Node *head=CreateList();
	cout<<"链表输出为:";
	VisitList(head);
	int k;
	while(cin>>k)
	{
		Node *temp=FindLastK(head,k);
		if(temp)
		{
			cout<<"倒数第"<<k<<"个元素为:"<<temp->value<<endl;
		}
		else
		{
			cout<<"输入的K超过了链表的长度!"<<endl;
		}
	}
	FreeList(head);//释放链表空间
	return 0;
}

         测试结果如下:


参考资料------《剑指offer》

展开阅读全文

没有更多推荐了,返回首页