說明:本文僅供學習交流,轉載請標明出處,歡迎轉載!
題目:給出一個單鏈表,返回倒數第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》