/* 1. 题目描述 */
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
/* 2. 提交记录 */
/*3. 算法思想 */
方法一:两次遍历法。
- 由题目可知,倒数第 n 个节点也即第 ( 链表长度len - n + 1 ),那么我们只需知道链表长度即可解决问题。
方法二:一次遍历法。
- 首先在原有链表 head 前插入一个头结点 firstNode 。
- 定义两个指针 q 和指针 p ,使得 q 和 p 间始终保持 n 个节点的距离,q 初始值 = firstNode;
- 然后在指针q,p间隔 n 个节点的前提下,q和p同时向下一个节点前进,直至 p = NULL ;
- 此时 q->next 节点即为需要删除的节点。需要注意最后返回的节点是 firstNode->next 而不能是head 节点。
/*4. 代码实现 */
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
int len = 1;
struct ListNode* p = head;
struct ListNode* q = head;
while(p->next != NULL){
q = p;
p = p->next;
len++;
}
if(n == len){ //删除首节点
head = head->next;
return head;
}
if(n == 1){ //删除尾节点
free(p);
q->next = NULL;
return head;
}
//删除中间节点
q = head;
p = q;
for(int i = 1;i <= len;i++){
if(i == len-n+1){
q->next = p->next;
return head;
}else{
if(p->next != NULL){
q = p;
p = p->next;
}else{ return NULL; }
}
}
return head;
}
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
struct ListNode* firstNode;
firstNode = (struct ListNode*) malloc(sizeof(struct ListNode));
firstNode->next = head;
struct ListNode* delNode = head;
struct ListNode* q = firstNode;
struct ListNode* p = firstNode->next;
for(int i = 1;i <= n;i++){
p = p->next;
}
while(p != NULL){
q = q->next;
p = p->next;
}
delNode = q->next;
q->next = delNode->next;
free(delNode);
head = firstNode->next;
return head;
}