目录
题目要求
题目理解以及思路分析
题目理解:
思路分析:
(一):找到“数组”(也就是链表)的长度 length
(二):技巧设立一个哑结点,让它的 next 指针指向链表的头节点。
(三):怎么找到删除的结点所处的位置?
代码分部讲解
第一部分
第二部分
第三部分
第四部分
给你一个链表,删除链表的倒数第 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来源:力扣(LeetCode)
很显然是一个 “链表” 的题目,关于链表,我之前一篇讲“哈希表”的时候曾讲过。其实就是一个数组。这一题的思路很好理解,下面我们就开始讲解吧。
这一题最终目的其实就是删除链表的倒数第 n 个结点,并返回链表的头结点。这样讲可能很多人仍然理解不了,说白了我们把链表当作一个一维数组,也就是说,我们找到这个数字倒数第 n 个数,将它删除,然后输出一个新的数组。就是这么简单。
题目理解了,那怎么具体的操作呢?,下面我们来一步一步的进行思路分析。
这一点很重要,我们只有找了其长度 length 我们才能找到倒数第 n 个数具体在哪?那问题来了,怎么知道给出的链表的长度呢?我的答案是遍历,从头结点开始一直遍历到最后一个结点,这样就得到了长度 length 。
为什么这么做?相信有些读者会产生疑惑。对于本题来说,要想删除一个结点,那我们必须要知道它的前驱结点,但是如果删除的是链表的头结点,我们怎么办?我们就必须进行一个判断,这样会更加的麻烦,所以我们直接设立一个 哑结点,令其作为头节点,这样我们就可以用统一的方法去求取。
这一步也是实现的代码很重要的程序。对问题进行数学分析,我们可以发现规律:那就是当我们从哑结点开始遍历时,等遍历到第 length +1 - n 个结点时,此时其下一个结点就是我们要删除的那个结点。
通过上述的理解和思路的分析,大家应该对这道题目有更深刻的理解,接下来我们便开始一步一步的讲解代码。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//这一步是用来求链表的长度的
int Length(struct ListNode* head)
{
int length = 0;//初始化链表的长度
while(head)
{
length++;
head = head -> next;
}
return length;
}
这一部分就是求题目所给链表的长度的,很简单,这里就不过多的解释了。
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
int i,length;
struct ListNode* rep = malloc(sizeof(struct ListNode)); //申请空间,进行分配
rep->val = 0,rep->next = head; //添加“哑结点”,将其作为新链表的头结点
这一步也很好理解:就是对原本的链表添加哑结点,原因我们在上面的思路分析中也讲过了。
length = Length(head); //调用函数,求链表的长度
struct ListNode*cur = rep; 定义一个链表
for(i=1;inext;
}
cur->next = cur->next->next;
struct ListNode* ans = rep->next; //定义一个新的链表,并且跳过添加的哑结点
return ans; //返回链表
}
这一步就比较难了,下面我们重点讲解一下:
for(i=1;i
next; } cur->next = cur->next->next; 首先是这一串代码,我们要理解它的含义:
它的目的就是将本该删去的结点位置用其下一个位置的结点覆盖掉
cur = cur->next;
这一步就是求出删除结点的前一位结点,也就是图里的 3 ,然后
cur->next = cur->next->next;
这一步就是将 3 的下一位结点用其下下位的结点 5 来代替,从然使得最终呈现的结果是:
之后,接下来就是最后一个代码了:
struct ListNode* ans = rep->next
定义一个新的链表,注意一定要是 rep->next ,此目的是为了去除我们之前添加的 哑结点。
完整的代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
int Length(struct ListNode* head)
{
int length = 0;
while(head)
{
length++;
head = head -> next;
}
return length;
}
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
int i,length;
struct ListNode* rep = malloc(sizeof(struct ListNode));
rep->val = 0,rep->next = head;
length = Length(head);
struct ListNode*cur = rep;
for(i=1;inext;
}
cur->next = cur->next->next;
struct ListNode* ans = rep->next;
return ans;
}