我的解法
依次遍历,然后创建一个hashmap来保存节点在列表的索引和结点指针
class Solution
{
public:
ListNode *removeNthFromEnd(ListNode *head, int n)
{
// 链表只有一个节点
if (head->next == nullptr)
{
head = nullptr;
return head;
}
unordered_map<int, ListNode *> node_map;
int count = 0;
auto begin = head;
// 将节点和索引的对应关系记录在hashmap中
while (begin != nullptr)
{
count++;
node_map[count] = begin;
begin = begin->next;
}
// 要删除的节点是尾节点
if (n == 1)
{
node_map[count - 1]->next = nullptr;
return node_map[1];
}
// 要删除头结点
else if (n == count)
{
auto begin = head->next;
head = nullptr;
return begin;
}
else
{
node_map[count - n]->next = node_map[count - n + 1]->next;
return node_map[1];
}
}
};
一个小技巧
引用官方题解 :
在对链表进行操作时,一种常用的技巧是添加一个哑节点(dummy node),它的 next指针指向链表的头节点。这样一来,我们就不需要对头节点进行特殊的判断了。
例如,在本题中,如果我们要删除节点 yy,我们需要知道节点 yy 的前驱节点 xx,并将 xx 的指针指向 yy 的后继节点。但由于头节点不存在前驱节点,因此我们需要在删除头节点时进行特殊判断。但如果我们添加了哑节点,那么头节点的前驱节点就是哑节点本身,此时我们就只需要考虑通用的情况即可。
class Solution1
{
public:
ListNode *removeNthFromEnd(ListNode *head, int n)
{
ListNode *dummy = new ListNode(0, head);
// 获取链表长度
auto begin = head;
int length = 0;
while (begin != nullptr)
{
begin = begin->next;
length++;
}
begin = dummy;
for (int i = 1; i < length - n + 1; i++)
{
begin = begin->next;
}
begin->next = begin->next->next;
auto ans = dummy->next;
delete dummy;
return ans;
}
};
使用栈
我们知道栈的顺序是先入后出,所以我们只需要遍历所有节点一遍,将他们依次入栈,然后在pop时便能方便的选到倒数第n个结点,在弹出了n个结点之后,在栈顶的就是倒数第n个结点的前驱节点。
class Solution2
{
public:
ListNode *removeNthFromEnd(ListNode *head, int n)
{
stack<ListNode *> node_stack;
ListNode *dummy = new ListNode(0, head);
auto begin = dummy;
while (begin != nullptr)
{
node_stack.push(begin);
begin = begin->next;
}
for (int i = 0; i < n; i++)
{
node_stack.pop();
}
auto ans = node_stack.top();
ans->next = ans->next->next;
return dummy->next;
}
};
快慢指针
看这篇文章已经讲的很详细了,我就不说什么了
class Solution3
{
public:
ListNode *removeNthFromEnd(ListNode *head, int n)
{
ListNode *dummy = new ListNode(0, head);
auto fast = dummy, slow = dummy;
for (int i = 0; i <= n; i++)
{
fast = fast->next;
}
while (fast != nullptr)
{
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummy->next;
}
};