Q:
Given a linked list, remove the nth node from the end of list and return its head.
For example, Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.
A:
(寫在最前面:兩種解法都特別要注意對(duì)dummy node和null node的處理)
一個(gè)指向(指針),跑兩遍鏈表:
public ListNode removeNthNode (ListNode node, int n){
ListNode dummy = new ListNode(0); //防止原鏈表第一個(gè)node被刪除
int length = 0;
int beforeTarget = 0; //定位到要?jiǎng)h除的node之前的node
dummy.next = head;
ListNode first = head;
while(first != null){
length ++;
first = first.next; //指向null為止
}
beforeTarget = length - n;
first = dummy;
while (beforeTarget > 0){
beforeTarget --;
first = first.next;//重新走一遍,走到要?jiǎng)h除的node之前的node停止
}
first.next = first.next.next;
return dummy.next;
}
.
如果鏈表里只有一個(gè)node:那么第一個(gè)while不執(zhí)行,計(jì)算beforeTarget
時(shí)為負(fù)值,第二個(gè)while也不執(zhí)行,執(zhí)行first.next = first.next.next
相當(dāng)于是執(zhí)行dummy.next=dummy.next.next
( =null )。不管n是多少,這個(gè)鏈表都被刪干凈了。
.
第一個(gè)while里面計(jì)數(shù)起點(diǎn)是帶著dummy鏈表里的第二個(gè)點(diǎn),因?yàn)槠瘘c(diǎn)指向dummy.next
,但第二個(gè)while里面計(jì)數(shù)起點(diǎn)是從dummy開(kāi)始的。
.
D -> 1 -> 2 -> 3 -> 4 -> 5 -> null
Length = 6,n = 2, 那么要?jiǎng)h的實(shí)際上是index值為5 = (L-n+1) 的node,所以,我們要找的前后兩個(gè)node分別為:(L-n) 和 (L-n+2),只考慮(L-n):beforeTarget = length - n;
,因?yàn)?L-n+2)僅是個(gè)數(shù)學(xué)表達(dá),它實(shí)際是通過(guò).next.next
來(lái)實(shí)現(xiàn)的。(一開(kāi)始,這種數(shù)學(xué)表達(dá)不太直觀,畫出圖,按代碼邏輯多測(cè)幾組數(shù)據(jù)就好了。)
兩個(gè)指針,first
和second
,只跑了一遍鏈表:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head; //其實(shí)參數(shù)head除了這里,后面都沒(méi)用到
ListNode first = dummy;
ListNode second = dummy;
for (int i = 1; i <= n + 1; i++) {
first = first.next; //第一個(gè)指針先跑,從head node開(kāi)始跑
}
while (first != null) {
first = first.next; //第一個(gè)指針跑到 null node 了,停!
second = second.next; //maintaing the same gap, gap是(n+1)個(gè)鏈條(->)
}
second.next = second.next.next; //指定的node被刪了
return dummy.next;
}
如果n=3,配個(gè)圖:
Notes:
由指針這件事,想到的Java和C++的區(qū)別:
.
- Java有回收機(jī)制,就不需要析構(gòu)函數(shù)了(deconstructor)
- Java沒(méi)有指針
- Java不能多重繼承
- Java的"123"是對(duì)象,C++中是const char*
- Java不能操作符重載
ArrayList vs Linked-list(Dynamic data structure)
.
ArrayList包裝了一個(gè)Object[],實(shí)例化的時(shí)候?qū)?yīng)一個(gè)數(shù)組,訪問(wèn)通過(guò).get(index)
,查找很方便,添加很麻煩,塞一個(gè)進(jìn)去,后面的位置都得挪,ArrayList是順序存儲(chǔ),而Linked-list是鏈?zhǔn)酱鎯?chǔ),這兩者都是Dynamic的 (Array是Static的)。增刪數(shù)據(jù)LinkedList改節(jié)點(diǎn)的引用就好了,方便。但是要遍歷節(jié)點(diǎn),速度慢。
(Lewis·Loftus Java Textbook page 619): A dynamic data structure is implemented using links. Using references as links between objects, we can create whatever type of structure is appropriate for the situation. If implemented carefully, the structure can be quite efficient to search and modify. Structures created this way are considered to be dynamic, because their size is determined dynamically, as they are used, and not by their declaration.