《劍指Offer》第二版之鏈表中倒數第k個節點(十)

目錄


題目:
輸入一個鏈表,輸出該鏈表中倒數第k個節點,爲了符合大多數人的習慣,本題從1開始計數,即鏈表的尾節點是倒數第一個節點。例如,一個鏈表有6個節點,從頭節點開始,他們的值依次是1、2、3、4、5、6。這個鏈表的倒數第3個節點是值爲4的節點。鏈表節點定義如下:
struct ListNode
{
	int m_nValue;
	ListNode m_pNext;
}

思路:
假設整個鏈表有n個節點,那麼倒數第k個節點就是從頭節點開始的第n-k+1個節點。如果我們能夠得到鏈表中節點的個數n,那麼只要從頭節點開始往後走n-k+1步就可以了。如何得到節點n?這個不難,只需要從頭節點開始遍歷鏈表,每經過一個節點,計數器加1就可以了。
也就是說我們需要遍歷鏈表兩次,第一次統計出鏈表中節點的個數,第二次就能找到倒數第k個節點。但是當我們把這種思路解釋給面試官之後,他會告訴我們他期待的解法只需要遍歷鏈表一次。
爲了實現只遍歷鏈表一次就能找到倒數第k個節點,我們可以定義兩個指針。第一個指針從鏈表的頭指針開始遍歷向前走k-1步,第二個指針保持不動;從第k步開始,第二個指針也開始從鏈表的頭指針開始遍歷。由於兩個指針的距離保持在k-1,當第一個(走在最前面)指針到達鏈表的尾節點時,第二個(走在最後面)指針正好指向倒數第k個節點。
步驟
1.首先用第一個指針從頭節點開始向前走兩(2=3-1)步到達第3個節點。 2.接着把第二個指針初始化指向鏈表的第一個節點。 3.最後讓兩個指針同時向前遍歷,當第一個指針到達鏈表的尾節點時,第二個指針指向的剛好就是倒數第3個節點。
代碼:
package test;

public class FindKthToTail {

	public static void main(String[] args) {
		ListNode ln1 = new ListNode();
		ListNode ln2 = new ListNode();
		ListNode ln3 = new ListNode();
		ListNode ln4 = new ListNode();
		ListNode ln5 = new ListNode();
		ListNode ln6 = new ListNode();
		ln1.value = 1;
		ln1.next = ln2;
		ln2.value = 2;
		ln2.next = ln3;
		ln3.value = 3;
		ln3.next = ln4;
		ln4.value = 4;
		ln4.next = ln5;
		ln5.value = 5;
		ln5.next = ln6;
		ln6.value = 6;
		ln6.next = null;
		System.out.println(findKthToTail(ln1, 3).value);
	}
	public static ListNode findKthToTail(ListNode pListHead, int k) {
		//1.校驗數據的合法性
		if(pListHead == null || k == 0) {
			return null;
		}
		
		ListNode pAhead = pListHead;
		ListNode pBehind = null;
		
		//2.將p1指針移動k-1個位置
		for (int i = 0; i < k - 1; i++) {
			if(pAhead.next != null)
				pAhead = pAhead.next;
			else
				return null;
		}
		
		//3.將p2指針從頭節點開始移動直到p1指針到達尾節點
		pBehind = pListHead;
		while(pAhead.next != null) {
			pAhead = pAhead.next;
			pBehind = pBehind.next;
		}
		
		return pBehind;
	}
	
	static class ListNode {
		int value;
		ListNode next;
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章