2020-3-24
Every boring hour in life is unique. 在生命中,再无聊的时光也是限量版。
题目:
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
个人解答:(C版本)
方法一:先求出链表长度len,然后就得出删除的节点为第len-n个节点了。(该方法更容易实现)方法二:让两个指针保持n-1的距离移动,当走在前面的指针到达末尾时,后面的指针指向的位置即为要删除的点。 有一个比较棘手的问题是如果删除的是头结点,这时可以考虑增加一个新的头结点,使原来的头结点不再特殊。 本代码示例采用方法二,详细的注释看下面代码。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
int interval = 0;
struct ListNode* q = NULL;
struct ListNode* p = NULL;
struct ListNode* t = NULL;
struct ListNode* headnode = NULL;
// 增加一下头指针,为了更好的应对删掉给定链表的第一个节点
headnode = (struct ListNode*)malloc(sizeof(struct ListNode));
// 将该节点作为新的节点
headnode->next = head;
p = t = q = headnode;
// p与q不断向后移动,两者保持n-1的距离,当q到达最后一个节点时,此时的p即为要删除的点
while(1)
{
q = q->next;
interval++;
if(interval >= n) // 此时p可以开始移动,之后就保持间隔
{
t = p; // t记录要p的前一个节点,方便删除p
p = p->next;
if(q->next == NULL)
{
// 删除并释放
t->next = t->next->next;
free(p);
break;
}
}
}
// 返回真正的头结点
head = headnode->next;
// 释放动态分配的内存
headnode->next=headnode;
free(headnode);
return head;
}
复杂度分析 1)一次循环就能找到结果,所以该算法的时间复杂度为O(n)。 2)由于只使用了少量的变量,空间复杂度为O(1)。
运行结果:
他山之石:
官方题解动图讲解