题目:
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后,链表变为 1->2->3->5.
方法一:遍历链表,获取链表长度len,删除链表第len-n+1个节点
#include "stdafx.h"
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
int Getlength(ListNode* head, int n) {
//获取链表长度
int len = 1;
while (head->next) {
head = head->next;
len++;
}
return len;
}
ListNode* removeNthFromEnd(ListNode* head, int n) {
if (head == nullptr || head->next == nullptr) return nullptr;
ListNode*p = head;
ListNode*q = head;
//获取链表长度
int len = Getlength(head, n);
//此时删除头结点 例如[1.2] n=2
if (len == n) {
head = head->next;
}
else {
int index = len - n - 1;
while (index && q->next) {
q = q->next;
index--;
}
p = q->next;
//[1,2,3,4,5] n=2
if (q->next->next) {
q->next = q->next->next;
}
//此时删除的是下一个节点 [1,2,3] n=1
else {
q->next = nullptr;
}
}
delete p;
p = nullptr;
return head;
}
ListNode * CreateNode(int n) //尾插法
{
ListNode *head = NULL, *pnew = NULL, *ptail = NULL; //创建表头、表尾和新插入结点并初始化
int num, i = 1;
while (i <= n)
{
pnew = new ListNode(0);
cout << "输入第" << i << "个结点:" << endl;
cin >> num;
pnew->val = num;
pnew->next = NULL;
if (head == NULL)
head = pnew;
else
{
ptail->next = pnew;
}
ptail = pnew;
i++;
}
pnew = NULL;
delete pnew;
return head;
}
int main()
{
int n = 0, m = 0; //结点个数
cout << "输入结点个数:" << endl;
cin >> n;
ListNode *head = CreateNode(n);
cout << "要删除的节点为倒数第:" << endl;
cin >> m;
ListNode *answer = removeNthFromEnd(head, m);
return 0;
}
方法二:
使用两根指针,指针间距离为n-1.当一根指针指向链表尾节点时,证明另一根指针所指节点应该被删除。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* pNode = head;
ListNode* fast = head;
ListNode* slow = head;
//使快指针移动n步,使其与慢指针之间保持一定距离
for (int i = 0; i < n; ++i) fast = fast->next;
if (fast == nullptr)
{
pNode = head->next;
delete head; head = nullptr;
return pNode;
}
//使快慢指针同步运动,直到快指针指向链表尾
while (fast->next != nullptr)
{
fast = fast->next;
slow = slow->next;
}
//使pNext指向该被删除的节点
ListNode* pNext = slow->next;
slow->next = pNext->next;
//释放空间
delete pNext; pNext = nullptr;
return head;
}
};