题目:删除链表的到数第N个结点(中等)
问题连接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
一、问题描述
给你一个链表,删除链表的倒数第 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
二、思路解析
暴力求解方法可以先对链表进行一次遍历数出链表元素个数,然后第二次遍历删除到数第N个元素,时间复杂度O(2n),暴力求解是很好实现的。
上面的方法时间复杂度为2n,所以需要想办法优化一下这个算法,首先因为是一个只给出头节点的单向链表,所以遍历只能从前向后遍历。那么可以构思一种双指针算法,当一个指针指向最后一个元素时让另一个指针刚好指向到数第n+1个元素,这样就可以只进行一次遍历就实现算法了
那么在初始化指针时就需要将指针先定位,然后同步向后遍历。
定义一个aim指针指向目标元素,定义一个last指针让他最终指向末尾。初始的时候就应该让两个指针保持一定距离,从上面的例子中就可以看出n=1时两个指针间隔为1的,n=2时两个指针间隔为2
所以在初始移动指针的时候就让last指针指向aim指针的后n个位置,然后再同时移动两个指针,当last指向最后一个元素时就删除aim这个位置的元素。
再考虑一种特殊情况,n=sz时,就是n等于元素个数,这时候要删除第一个元素,但是因为链表的数据结构中并没有记录链表长度,所以链表长度是未知的。那么就需要判断n是否等于链表长度了。
可以尝试再定位last和aim的时候完成这个操作,假设链表中有两个元素,而此时n=2,那么在定位的时候aim指向了第一个元素,而last会指向最后一个元素的下一个位置,也就是null。所以在定位的时候我们需要对last进行一个判断,如果last在定位完成后指向了null,就因该删除第一个元素。
三、代码
数据结构为:
四、总结
链表删除操作关键在于记录被删除结点的前一个位置,而且单向链表只能朝一个方向遍历,所以有的时候采用双指针对链表进行一个定位可能是一个好思路
leetcode每日一题(2021.5.23)——删除链表的到数第N个结点
原文:https://www.cnblogs.com/zyq79434/p/14802105.html