一、解題思路
- 涉及鏈表的特殊位置,考慮快慢指針
- 要刪除鏈表的節點,先找到它的前驅
二、刪除鏈表的倒數第n個節點
刪除鏈表倒數第n個節點
輸入:head = [1,2,3,4,5], n = 2
輸出:[1,2,3,5]
@@@@兩種解題思路:
-
推薦
通過快慢指針找到要刪除節點的前驅節點,然后刪除 -
不推薦
通過坐標:先得到鏈表的總長度,然后計算得到要刪除元素的前驅節點的坐標,最后刪除,
注意區分
鏈表數據結構的特點和數組數據結構的特點,數組偏向于用坐標,鏈表傾向于用指針
1、 (推薦)快慢指針解題思路:
- 初始時fast和slow 均指向頭節點
- 讓fast比slow超前 n 個節點
- 然后同時讓fast和slow向后移動。當fast移動到鏈表的末尾(即 fast.next為null)時,slow 恰好指向倒數第 n 個節點的前驅節點
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
if(n<=0){return false}
let fast = head
let slow = head
let i = 0
//初始化快慢指針的位置,中間相隔n
while(i<n){
fast = fast.next
i++
}
//結束時fast已到最后一個
//slow此時是倒數第n個節點的前驅節點
while(fast.next){
fast = fast.next
slow = slow.next
}
slow.next = slow.next.next
return head
};
2、坐標法解題思路:
- 循環得到鏈表的長度(或者將鏈表轉為數組拿到數組長度)
- 計算要刪除元素前驅節點的坐標,拿到前驅節點
- 刪除
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
// 循環得到鏈表的總長度
let len = getLen(head);
//前驅節點的下標 4-2=2
let preNum = len-n;
let k = 0
let pre = head
//拿到前驅節點
while(k<preNum){
//0-1
pre = pre.next
k++
}
//刪除元素
pre.next=pre.next.next
return head
};
//循環得到鏈表長度
function getLen(head){
let i = 0
while(head.next){
head = head.next
i+=1
}
return i
}
//把鏈表轉為數組拿到鏈表長度
function getArrLen(head){
let arr = []
while(head){
arr.push(head.val)
head = head.next
}
return arr.length
}