[剑指offer]面试题15:链表中倒数第k个结点
面試題15:鏈表中倒數第k個結點
題目:輸入一個鏈表,輸出該鏈表中倒數第 k 個結點。為了符合大多數人的習慣,本題從1 開始計數,即鏈表的尾結點是倒數第1 個結點。例如一個鏈表有6個結點,從頭結點開始它們的值依次是1、2、3、4、5、6。這個鏈表的倒數第3個結點是值為4的結點。
鏈表結點定義如下:
為了實現只遍歷鏈表一次就能找到倒數第 k 個結點,我們可以定義兩個指針。
第一個指針從鏈表的頭指針開始遍歷向前走k-1,第二個指針保持不動;
從第 k 步開始,第二個指針也開始從鏈表的頭指針開始遍歷。
由于兩個指針的距離保持在k-1,當第一個(走在前面的)指針到達鏈表的尾結點時,第二個指針(走在后面的)指針正好是倒數第k個結點。
代碼如下:
ListNode *FindKthToTail(ListNode *pListHead, unsigned int k) {ListNode *pAhead = pListHead;ListNode *pBehind = nullptr;for (unsigned int i = 0; i < k - 1; i++){pAhead = pAhead->next;}pBehind = pListHead;while (pAhead->next != nullptr){pAhead = pAhead->next;pBehind = pBehind->next;}return pBehind; }以上面的代碼為例,面試官可以找出3種辦法讓這段代碼崩潰:
寫代碼要特別注意魯棒性。
針對前面指出的 3 個問題,我們要分別處理。
修改之后的代碼如下:
ListNode *FindKthToTail(ListNode *pListHead, unsigned int k) {if (pListHead == nullptr || k == 0) return nullptr;ListNode *pAhead = pListHead;ListNode *pBehind = nullptr;for (unsigned int i = 0; i < k - 1; i++){if (pAhead->next != nullptr){pAhead = pAhead->next;}else return nullptr;}pBehind = pListHead;while (pAhead->next != nullptr){pAhead = pAhead->next;pBehind = pBehind->next;}return pBehind; }測試用例:
● 功能測試(第k 個結點在鏈表的中間,第k 個結點是鏈表的頭結點,第k個結點是鏈表的尾結點)。
● 特殊輸入測試(鏈表頭結點為 NULL 指針,鏈表的結點總數少于k,k等于0)。
本題考點:
● 考查對鏈表的理解。
● 考查代碼的魯棒性。魯棒性是解決這道題的關鍵所在。如果應聘者寫出的代碼有著多處崩潰的潛在風險,那么他是很難通過這輪面試的。
相關題目:
● 求鏈表的中間結點。如果鏈表中結點總數為奇數,返回中間結點;如果結點總數是偶數,返回中間兩個結點的任意一個。為了解決這個問題,我們也可以定義兩個指針,同時從鏈表的頭結點出發,一個指針一次走一步,另一個指針一次走兩步。當走得快的指針走到鏈表的末尾時,走得慢的指針正好在鏈表的中間。
● 判斷一個單向鏈表是否形成了環形結構。和前面的問題一樣,定義兩個指針,同時從鏈表的頭結點出發,一個指針一次走一步,另一個指針一次走兩步。如果走得快的指針追上了走得慢的指針,那么鏈表就是環形鏈表;如果走得快的指針走到了鏈表的末尾(m_pNext指向NULL)都沒有追上第一個指針,那么鏈表就不是環形鏈表。
總結
以上是生活随笔為你收集整理的[剑指offer]面试题15:链表中倒数第k个结点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 教你如何DIY组装电脑主机
- 下一篇: Redisson分布式锁