重磅乾貨,第一時間送達程序員
鏈表中倒數第k個節點面試
輸入一個鏈表的頭結點,從尾到頭反過來打印出每一個結點的值正則表達式
爲了獲得倒數第k個結點,很天然的想法是先走到鏈表的尾端,再從尾端回溯k步。當時,從鏈表結點的定義能夠看出本題中的鏈表是單向鏈表,單向鏈表的結點只有從前日後的指針而沒有從後往前的指針,所以這種思路行不通,它只適用於雙向鏈表。
思路:看到本題咱們很天然的一個想法是從尾結點往前倒退k步,可是對於單鏈表是行不通的。那咱們換個思路,假設鏈表有n個結點,要求倒數第k個結點,其實也就是從前日後數第n-k+1個結點,這個思路只須要遍歷兩次鏈表便可。 算法
有沒有隻遍歷一次鏈表的方法呢?本題實際上是很典型的快慢雙指針問題,快指針先走k步,而後快慢指針再同時往前走,當快指針走到盡頭時,慢指針恰好在倒數第k個節點的位置上。這樣只須要遍歷一次鏈表便可。惟一須要注意的問題是當心參數k值大於鏈表長度。數組
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def FindKthToTail(self, head, k): # write code here pre = post = head # 快指針先走k步 for i in range(k): # 若是k大於鏈表長度,返回空 if pre == None: return None pre = pre.next # 快慢指針同時往前走 while pre != None: pre = pre.next post = post.next return post
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { // 查找倒數第0個節點和輸入空指針 if(pListHead == NULL || k == 0){ return NULL; } // 兩個指針遍歷鏈表 ListNode *pAhead = pListHead; ListNode *pBehind = pListHead; // 第一個指針從鏈表的頭結點走K-1步 for(unsigned int i = 0; i < k - 1; i++){ if(pAhead->next != NULL){ pAhead = pAhead->next; } else{ return NULL; } } // 第k個節點開始,兩個指針同時遍歷 while(pAhead->next != NULL){ pAhead = pAhead->next; pBehind = pBehind->next; } return pBehind; } };
/** * 輸入一個鏈表,輸出該鏈表中倒數第k哥結點。 * 爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾結點是倒數第1個結點。 * 例如一個鏈表有6個結點,從頭結點開始它們的值依次是1,2,3,4,5,6.這個鏈表的倒數第3個結點是值爲4的結點 */ package swordForOffer; import utils.ListNode; public class E15KthNodeFromEnd { public ListNode FindKthToTail(ListNode head,int k){ if(head == null || k <= 0){ return null; } ListNode ANode = head; ListNode BNode = null; for(int i = 0;i<k-1;i++){ if(ANode.next != null) ANode = ANode.next; else return null; } BNode = head; while(ANode.next != null){ ANode = ANode.next; BNode = BNode.next; } return BNode; } public static void main(String[] args){ ListNode head = new ListNode(); ListNode second = new ListNode(); ListNode third = new ListNode(); ListNode forth = new ListNode(); head.next = second; second.next = third; third.next = forth; head.data = 1; second.data = 2; third.data = 3; forth.data = 4; E15KthNodeFromEnd test = new E15KthNodeFromEnd(); ListNode result = test.FindKthToTail(head, -1); System.out.println(result); } }
注:面試季來了,無論是做爲面試者仍是之後做爲面試官,瞭解算法這門程序員之間的溝通方式都是很是必要的。找過工做的朋友應該都據說過《劍指offer》,雖然書中只有六十多道題目,可是道道都是經典。微信
若是是單純的面試需求,劍指offer的優先級確定是在Leetcode以前,總的說它有三個優勢:數據結構
它的缺點是:機器學習
劍指offer刷題交流羣ide
掃碼添加微信,必定要備註研究方向+地點+學校+暱稱(如機器學習+上海+上交+湯姆)函數
▲長按加羣