19. 删除链表的倒数第 N 个结点
难度 中等
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
- 链表中结点的数目为
sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
**进阶:**你能尝试使用一趟扫描实现吗?
题解
这道题是一道关于数组遍历的题目,主要是想要大家懂的如何一次遍历找到倒数第k个元素。这个算法是在考研数据结构中第一次接触到的,母题是求倒数第K个元素,按正常思路,一般都是遍历一遍,知道数组长度,然后遍历n-k次就得到倒数第k和元素了,但是这样不是最优解。然后看到答案最优解是一次遍历,设置一个指针先走k步,然后另外一个指针才开始一起移动,这样先走k步的指针先到达数组末尾。当到达数组末尾的时候另外一个指针就相差k步,刚好就是倒数第k个元素。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
struct ListNode* dumy = malloc(sizeof(struct ListNode));//新建头指针
dumy->next=head;
struct ListNode* p=head;//p指向第一个节点
struct ListNode* q=dumy;//q指向头指针
for(int i=0;i<n;i++){//先走n步
p=p->next;
}
while(p){//同时移动
p=p->next;
q=q->next;
}
q->next=q->next->next;//跳过节点
struct ListNode* ans = dumy->next;//ans指向头结点
free(dumy);
return ans;
}