題目
給定一個(gè)鏈表,刪除鏈表的倒數(shù)第 n 個(gè)節(jié)點(diǎn),并且返回鏈表的頭結(jié)點(diǎn)。
示例:
給定一個(gè)鏈表: 1->2->3->4->5, 和 n = 2.
當(dāng)刪除了倒數(shù)第二個(gè)節(jié)點(diǎn)后,鏈表變?yōu)?1->2->3->5.
說明:
給定的 n 保證是有效的。
進(jìn)階:
你能嘗試使用一趟掃描實(shí)現(xiàn)嗎?
頭節(jié)點(diǎn)的應(yīng)用
(引用百度百科)
講到鏈表不得不講到頭節(jié)點(diǎn),數(shù)據(jù)結(jié)構(gòu)中,在單鏈表的第一個(gè)結(jié)點(diǎn)之前附設(shè)一個(gè)結(jié)點(diǎn),它沒有直接前驅(qū),稱之為頭結(jié)點(diǎn)
頭結(jié)點(diǎn)是鏈表里面第一個(gè)結(jié)點(diǎn),他的數(shù)據(jù)域可以不存放任何信息(有時(shí)候也會(huì)存放鏈表的長(zhǎng)度等等信息),他的指針區(qū)域存放的是鏈表中第一個(gè)數(shù)據(jù)元素的結(jié)點(diǎn)(就是傳說中的首元結(jié)點(diǎn))存放的地址。
- 防止單鏈表是空的而設(shè)的.當(dāng)鏈表為空的時(shí)候,帶頭結(jié)點(diǎn)的頭指針就指向頭結(jié)點(diǎn).如果當(dāng)鏈表為空的時(shí)候,頭結(jié)點(diǎn)的指針域的數(shù)值為NULL.
- 是為了方便單鏈表的特殊操作,插入在表頭或者刪除第一個(gè)結(jié)點(diǎn).這樣就保持了單鏈表操作的統(tǒng)一性!
- 單鏈表加上頭結(jié)點(diǎn)之后,無論單鏈表是否為空,頭指針始終指向頭結(jié)點(diǎn),因此空表和非空表的處理也統(tǒng)一了,方便了單鏈表的操作,也減少了程序的復(fù)雜性和出現(xiàn)bug的機(jī)會(huì) 。
思路
- 鏈表的結(jié)構(gòu)特殊,沒有辦法根據(jù)倒數(shù)位置直接定位到該位置的具體索引值,因?yàn)槭孪炔恢梨湵淼拈L(zhǎng)度,如果設(shè)置一個(gè)快指針和慢指針,令他們的的距離為n,然后一起滑動(dòng),這樣,當(dāng)快指針到達(dá)終點(diǎn)的時(shí)候,慢指針下一個(gè)指向剛好就行需要?jiǎng)h除的節(jié)點(diǎn)
- 設(shè)置一個(gè)頭指針preNode,preNode.next=head
- 設(shè)置快指針fastNode=preNode,慢指針slowNode=preNode
- 循環(huán)n次,讓fastNode前進(jìn)n步
- 繼續(xù)循環(huán),直到fastNode到達(dá)鏈表尾端,這樣慢節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)剛好就是要?jiǎng)h除的節(jié)點(diǎn)
圖解
用ppt做的gif
圖解算法.gif
代碼
public class removeNthFromEnd {
public ListNode removeNthFromEndSolution(ListNode head, int n) {
ListNode preNode = new ListNode(0);
preNode.next = head;
ListNode fastNode = preNode, slowNode = preNode;
while (n > 0) {
fastNode = fastNode.next;// 采用快慢節(jié)點(diǎn)
n--;
}
while (fastNode.next != null) {
fastNode = fastNode.next;
slowNode = slowNode.next;// 快慢節(jié)點(diǎn)距離始終一致,等快節(jié)點(diǎn)到終點(diǎn)的時(shí)候,慢節(jié)點(diǎn)剛好落在了需要?jiǎng)h除的那個(gè)節(jié)點(diǎn)上面
}
slowNode.next = slowNode.next.next;// 刪除節(jié)點(diǎn)
return preNode.next;
}
}