「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」
题目_删除链表的倒数第 N 个结点
给你一个链表,删除链表的倒数第 n **个结点,并且返回链表的头结点。
示例 1:
思路:
一看到这个题,就想到双指针解法。
- 定义两个指针first和second
- 先让first从头节点向前走n-1步
- 这时再让second也从头节点开始向前走,当first到达尾节点的时候,second刚好在第n个节点的前一个节点。
- 这时再进行节点删除操作即可
说时迟那时快,代码赶紧撸出来
第二次才通过,因为如果删的刚好是头节点,有点麻烦,我的处理是first和second指针都是fakeNode,他们都指向head,那么需要删头节点的话,只需要改变second的指针就好了。
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
if(head == null){
return ;
}
let first = new ListNode(0);
let second = new ListNode(0);
first.next = head;
second.next = head;
while(first.next){
if(n>0){
n--
}else{
second = second.next;
}
first = first.next;
}
if(second.next == head){
return head.next;
}else{
second.next = second.next.next;
return head;
}
};
官方题解
看了题解,给了三种方法
1.遍历整个链表,计算长度l,再遍历一遍,遍历到l-n的时候执行删除操作
2.使用栈,遍历完之后,再遍历栈,弹出第n个
3.双指针
很开心,我的暴力解法就是目前看来比较好的解法。
官方题解在我的解法上做了一些优化,
- first可以不用是fakeNode。
- return的时候可以不用做头节点的判断,提前把second存一份到变量fakeNode,return的时候就return这个fakeNode的next即可
贴出官方代码如下
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
let fakeNode = new ListNode(0)
fakeNode.next = head;
let first = head;
let second = fakeNode;
for(let i=0;i<n-1;i++){
first = first.next;
}
while(first.next){
first = first.next;
second = second.next;
}
second.next = second.next.next;
let answer = fakeNode.next;
return answer;
};