一、前言
今天的题目是比较简单的主要是注意要使用虚拟头结点吧,这个是卡哥强调的也是我认为的重点对于链表来说是个不错的小技巧,请各位uu自行尝试吧,话不多说直接上题吧。
二、题目(力扣第19题. - 力扣(LeetCode))
给你一个链表,删除链表的倒数第 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]
三、题解
这个题目个人感觉卡哥的思路也很好是最开始的双指针,具体讲解放到这里了(代码随想录),但是对于这个题来说,给了结点倒数位置(n),因此我们只需要只知道整个链表长度(length)就可以用length-n来得到正向的要输出元素的位置即可,但是链表并没有求长度的函数,不像vector可以直接使用size或者length函数来得到长度,所以我们需要遍历链表,从而得到链表长度即可。接下来上示意图和代码。
1、示意图
原链表:
引入虚拟头结点:
使用tail来遍历链表得到链表长度
while(tail){//tail遍历链表得到链表长度co
len++;
tail=tail->next;
}
然后使用ncur来移动到第len-n-1个结点(被删除结点的前一个结点)
直接删除第len-n个结点
ncur->next=ncur->next->next;//直接删除第len-n个结点
这样就完成了删除倒数第n个结点的任务了。
2、代码:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *prehead=new ListNode(-1);//引入虚拟头结点
prehead->next=head;
ListNode *tail=head;//tail用来遍历链表得到链表长度
int len=0;//储存链表长度
while(tail){//tail遍历链表得到链表长度co
len++;
tail=tail->next;
}
ListNode *ncur=prehead;//用来删除倒数第n个结点(也就是正向第len-n个结点)
for(int i=0;i<=len-n-1;++i){//正向遍历到第len-n-1(删除结点的前一个结点)
ncur=ncur->next;
}
ncur->next=ncur->next->next;//直接删除第len-n个结点
return prehead->next;//返回头结点(不要返回head因为可能head也会被删除)
}
四、后记
刚开始的我并没有引入头结点,而是直接返回的head这样的话就会增加一定的代码来判断删除后head是否存在就会麻烦一些,因此引入虚拟头结点以后返回虚拟头结点的next结点就完美的避开了这个问题(虚拟头结点yyds只能说)。然后就是对于处理倒数第n个结点的问题,卡哥的思路是双指针然后让fast先移动n个结点,然后slow和fast就相差n个结点,两者同时移动,当fast到尾结点时,自然slow就指向了倒数第n个结点,这样的方法也很不错。但是我觉得对于位置的处理可以先考虑知道整个数据结构的长度然后再进行变换即可,因为存在size和length这样的求长度函数同时即使自行遍历也很方便得到整个长度,倒数第n个结点也就是正向的第len-n个结点,这样也比较简单。各位uu加油,相信我们都有光明的未来!!!