java 链表删除头结点,删除链表的倒数第N个节点,并返回链表的头节点
面試的時候遇到了一個筆試題,是leetcode的原題,原題的連接:
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
大概的內容:刪除鏈表的倒數第N個節點,并返回鏈表的頭節點。
一開始遇到這個題也是一臉懵,通過查看解題思路才了解到有幾種解決方式:
單向項鏈表實現類:
public?class?ListNode?{
int?val;
ListNode?next;
ListNode(int?x)?{?val?=?x;?}
}
0x01:兩次循環求長度
實現思路:
1、先循環一遍鏈表,求出鏈表的長度L,倒數第N個節點就是從開頭數第(L-N+1)個節點,將此節點的next指向下下節點就可以了。
在解題的過程中要添加一個亞節點(dummy)進行輔助(如:圖1),D就是我們的亞節點。
圖1
代碼:
ListNode?dummy?=?new?ListNode(0);//亞節點
dummy.next?=?head;
int?length?=?0;
ListNode?first?=?head;
//通過移動頭節點循環求出鏈表的長度
while(first?!=?null){
length++;
first=first.next;
}
length?-=?n;//計算要刪除節點位置
first?=?dummy;
while(length?>?0){
length?--;
first?=?first.next;
}
first.next?=?first.next.next;
return?dummy.next;//返回頭節點
0x02:雙指針
實現思路:
1、定義兩個指針同時指向我們的亞節點。
2、第一個指針節點向前移動N+1步,第二個指針保持不動,這時兩個指針相隔N個節點的距離
3、同時移動兩個指針保持恒定的距離,直到第一個指針到達最后一個節點。
4、這時第二個指針所指向的節點的下一個節點就是要刪除的節點(倒數第N個節點),將第二個指針指向的節點的next指向下下個節點就完成了。
圖2
代碼:
ListNode?dummy?=?new?ListNode(0);//亞節點
dummy.next?=?head;
ListNode?first?=?dummy;//第一個指針
ListNode?secound?=?dummy;//第二個指針
for(int?i?=?0;?i
first=?first.next;
}
while(first?!=?null){//同時移動第一個指針和第二個指針直到第一個指針指向null
first?=?first.next;
secound?=?secound.next;
}
secound.next?=?secound.next.next;
return?dummy.next;
我們能看到方法二比方法一代碼簡潔一些,雙指針也是算法題里面比較常用的解題方法。
仔細查看評論區我們又看到不錯的解題思路,使用遞歸方法和特性實現
0x03:遞歸的特性
實現思路:
1、利用遞歸調用的特性先循環一遍鏈表,相當于用指針從鏈表頭走到鏈表尾(如:圖3-2)
2、遞歸調用在調用自身方法后面會倒敘的循環調用,相當于指針在從尾節點執行到頭節點,這時在第N步將指針指向的節點的next指向下下個節點就完成了。
這里遞歸的特性和使用會在后面單獨寫一篇文章來說明。
圖3-1
圖3-2
代碼:
public?static?ListNode?removeNthFromEnd(ListNode?head,?int?n){
int?pos?=?helper(head,?n);
//?說明刪除的是頭節點
if(pos?==?n?-?1)?{
return?head.next;
}
return?head;
}
//?獲取節點所在位置,逆序
public?int?helper(ListNode?node,?int?n){
if(node.next?==?null)?{
return?0;
}
int?pos?=?helper(node.next,?n)?+?1;
if(pos?==?n)?{
node.next?=?node.next.next;
}
return?pos;
}
source:https://www.cnblogs.com/stevewys/articles/13252439.html
喜歡,在看
總結
以上是生活随笔為你收集整理的java 链表删除头结点,删除链表的倒数第N个节点,并返回链表的头节点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php链接中二维数组传参数,JS用POS
- 下一篇: java父系调用子系,获取usb设备父系