題目:輸入一個鏈表,輸出該鏈表中倒數第 k 個節點。爲了符合大多數人的習慣,本題從 1 開始計數,即鏈表的尾節點是倒數第一個節點。ios
爲了獲得倒數第 k 個節點,很天然的想法就是:首先走到鏈表的尾端回溯 k 步。然而,單向鏈表的節點只有從前向後的指針,沒有從後往前的指針,這種思路是行不通的。spa
既然不能從尾節點遍歷單鏈表,咱們仍是把思路回到單鏈表的頭結點。假設整個鏈表有 n 個節點,那麼倒數第 k 個節點就是,從頭開始的第 n - k + 1 個節點。如何得知整個鏈表的節點數目? 只要從頭遍歷鏈表,每通過一個節點,計數器加 1 便可。也就是說,這種方法須要遍歷兩次單鏈表。第一次,統計鏈表中的節點數目; 第二次,就可以找到倒數第 k 個節點。指針
3)若是要求只能遍歷一次單鏈表。咱們能夠定義兩個指針。第一個指針從鏈表的頭指針開始遍歷向前走 k - 1 步,第二個指針保持不動;從第 k 步開始,第二個指針也從單鏈表的頭指針開始遍歷,兩個指針始終保持 k - 1,當第一個指針走到(走在前面的指針)鏈表的尾節點時,第二個指針(走在後面的)正好指向的是鏈表的倒數第 k 個節點。【使用的是快慢指針】內存
寫代碼時存在的三個潛在的風險:ci
1)輸入的頭指針爲 NULL的時候,因爲代碼會試圖訪問空指針指向的內存,程序會崩潰io
2)當輸入的頭指針所指向的單鏈表的結點個數不足 k 個的時候。因爲在for 循環中,程序會向前中 k - 1 步,程序就會崩潰。stream
3)輸入的參數爲 k 爲 0,因爲k 是一個無符號整數,那麼在 for 循環中 k - 1 將獲得的不是 -1,所以 for 循環的次數遠遠超乎咱們的想象,一樣會形成程序的崩潰。List
//輸入一個鏈表,輸出鏈表的倒數第 k 個節點[使用兩個指針:快慢指針]
#include<iostream>
using namespace std;循環
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}ListNode, *LinkList;遍歷
LinkList CreateLinkList(LinkList L)
{
if(L == NULL)
{
L = new LNode();
L->next = NULL;
}
return L;
}
void InsertLinkList(LinkList L, ElemType value)
{
if(L == NULL)
return;
LNode *p, *s;
s = L;
p = new LNode();
p->data = value;
p->next = s->next;
s->next = p;
}
LNode* FindKthToTail(LinkList L, int k)
{
if(L == NULL || k == 0) //鏈表爲空或者輸入的 k 不合法時,返回NULL
return NULL;
LNode *pNode = L;
LNode *pBegin = NULL;
for(int i = 0; i < k - 1; i++)
{
if(pNode->next != NULL) //若是第一個指針指向的下一個元素不爲空時,則向後移動第一個指針
pNode = pNode->next;
else
return NULL; //不然,返回NULL,此時說明,單鏈表的節點數目不足 k 個
}
pBegin = L;
while(pNode->next != NULL) //移動第一個指針,直至第一個指針指向最後一個節點
{
pNode = pNode->next;
pBegin = pBegin->next; //移動第二個指針
}
return pBegin; //返回第二個指針,其指向的正是倒數第 k 個節點
}
int main()
{
LNode *L, *result;
L = NULL;
result = NULL;
L = CreateLinkList(L);
int value;
while(cin >> value)
{
InsertLinkList(L, value);
}
result = FindKthToTail( L, 1);
cout << result->data << endl;
system("pause");
return 0;
}
相關題目:
1)求鏈表的中間節點:若是鏈表的節點總數爲奇數,返回中間節點;若是節點的總數爲偶數,則返回中間兩個節點中的任意一個。【解決該問題,也能夠定義兩個指針,同時從鏈表的頭結點開始出發,第一個指針一次走一步,第二個指針一次走兩步。當第二個指針走到鏈表的末尾的時候,走得慢的指針正好走到鏈表的中間。】
2)判斷一個單鏈表是否造成了一個環形結構【一樣的定義兩個指針,同時從鏈表的頭結點開始出發,一個指針一次走一步,另外一個指針一次走兩步。若是走的快的指針追上了走得慢的指針,則說明鏈表是環形的。若是走得快的指針走到了鏈表的末尾都沒有追上走得慢的指針,則說明鏈表不是環形的。】