题目描述:
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
题目解答:
方法1:双指针
为了防止特殊情况,申请一个空的头节点,让原链表跟在头结点之后。设计两个指针,一个指向与头结点,另一个指向与头结点距离为n
的位置,即两指针之间距离为n
。然后同时遍历两个指针,直到第二个指针的next
为空,此时第一个指针的next
就是要删除的节点。运行时间4ms,代码如下。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode* front = (struct ListNode*)malloc(sizeof(struct ListNode));
front->next = head;
struct ListNode *t1 = front, *t2 = front;
int i = 0;
for(i = 0; i < n; i++)
t2 = t2->next;
while(t2->next) {
t1 = t1->next;
t2 = t2->next;
}
struct ListNode* delete = t1->next;
t1->next = delete->next;
free(delete);
t1 = front->next;
free(front);
return t1;
}
方法2:两次遍历
第一次遍历先统计出节点总数sum
,然后用总数sum
减去n
,根据得到的结果从头再一次遍历,找到要删除的节点。