自我小结
LeetCode题目:删除链表的倒数第N个结点(中等)
题目描述:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:给定的 n 保证是有效的。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的答案
方法一:快慢指针
1、第18行的while循环中,p=slow;和slow=slow->next;两者顺序不能颠倒,否则将删除待删结点的下一结点。
2、草稿纸上画一个简图能更好的理解过程。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
if (!head || n<=0) return NULL; //非法处理
struct ListNode *fast=head,*slow=head,*p=NULL; //定义快慢指针和待删结点的前驱结点指针
int i = 0;
while (i<n){ //快指针先走n步
fast = fast->next;
i ++;
}
while (fast){ //当快指针没有走到最后时,快慢指针同时走1步
p = slow; //前驱结点赋值为慢指针,之后慢指针走1(不能颠倒)
slow = slow->next;
fast = fast->next; //若快指针的next为NULL时,慢指针的下一个接结点刚好为待删结点
}
if (p)
p->next = p->next->next; //如果前驱结点存在,则删除待删结点
else head = slow->next; //否则说明待删结点为头结点
return head;
}
方法二:按下标查找
第15行需要对结点进行判空,否则LeetCode的编译器将提示运行时错误。
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
int length=0,former=0; //链表长度置0,待删结点的前一个结点下标置0
struct ListNode *p = head,*res = head; //指针p用于遍历链表,指针res用于返回
if (!head || n<=0) return NULL; //非法处理
while (p){ //计算链表长度
length ++;
p = p->next;
}
former = length - n; //待删结点的前一结点下标
if (former == 0) res = head->next; //说明待删结点为头结点
for (int i=1; i<former; i++){ //否则指针走到待删结点前一结点
head = head->next;
}
if (!head->next) return NULL; //结点判空
head->next = head->next->next; //删除待删结点
return res;
}
小结
1、首先想到的是第二种方法,通过对应下标来查找和删除,万万没想到也可以用双指针的方法来做。
2、通过LeetCode评论区得知一般带有间距问题的都可以用双指针来做,但要知道两颗指针应该怎么走才能满足题目条件;看来双指针确实是个很棒的方法,需要多加了解学习才能运用于实际。
(注:小白一枚,欢迎指正,多多包涵)