从给定链表的末尾删除第 N 个节点
给定一个链表和一个整数N ,任务是从给定链表的末尾删除第N个节点。
例子:
Input: 2 -> 3 -> 1 -> 7 -> NULL, N = 1
Output:
The created linked list is:
2 3 1 7
The linked list after deletion is:
2 3 1
Input: 1 -> 2 -> 3 -> 4 -> NULL, N = 4
Output:
The created linked list is:
1 2 3 4
The linked list after deletion is:
2 3 4
直觉:
令K为链表中的总节点数。
观察:第N次 从末尾开始的节点是从头开始的第(KN)个节点。
所以问题简化为我们必须从一开始就找到第(KN)个节点。
- 一种方法是在一次传递中找到链表的长度(K) ,然后在第二次传递(KN)步骤中从开始到从结束到达第N个节点。
- 一次完成。让我们取第一个指针并移动N步 从一开始就。现在第一个指针距离最后一个节点(KN)步,这与第二个指针从开始移动到从结束到达第N个节点所需的步数相同。
方法:
- 取两个指针;第一个将指向链表的头部,第二个将指向从头开始的第N个节点。
- 现在继续将两个指针同时加一个,直到第二个指向链表的最后一个节点。
- 经过上一步的操作后,第一个指针现在应该指向从末尾开始的第N个节点。因此,删除第一个指针指向的节点。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
class LinkedList
{
public:
// Linked list Node
class Node
{
public:
int data;
Node* next;
Node(int d)
{
data = d;
next = NULL;
}
};
// Head of list
Node* head;
// Function to delete the nth node from
// the end of the given linked list
Node* deleteNode(int key)
{
// We will be using this pointer for holding
// address temperorily while we delete the node
Node *temp;
// First pointer will point to
// the head of the linked list
Node *first = head;
// Second pointer will point to the
// Nth node from the beginning
Node *second = head;
for (int i = 0; i < key; i++)
{
// If count of nodes in the given
// linked list is <= N
if (second->next == NULL)
{
// If count = N i.e.
// delete the head node
if (i == key - 1){
temp = head;
head = head->next;
free (temp);
}
return head;
}
second = second->next;
}
// Increment both the pointers by one until
// second pointer reaches the end
while (second->next != NULL)
{
first = first->next;
second = second->next;
}
// First must be pointing to the
// Nth node from the end by now
// So, delete the node first is pointing to
temp = first->next;
first->next = first->next->next;
free (temp);
return head;
}
// Function to insert a new Node
// at front of the list
Node* push(int new_data)
{
Node* new_node = new Node(new_data);
new_node->next = head;
head = new_node;
return head;
}
// Function to print the linked list
void printList()
{
Node* tnode = head;
while (tnode != NULL)
{
cout << (tnode->data) << ( " ");
tnode = tnode->next;
}
}
};
// Driver code
int main()
{
LinkedList* llist = new LinkedList();
llist->head = llist->push(7);
llist->head = llist->push(1);
llist->head = llist->push(3);
llist->head = llist->push(2);
cout << ("Created Linked list is:\n");
llist->printList();
int N = 1;
llist->head = llist->deleteNode(N);
cout << ("\nLinked List after Deletion is:\n");
llist->printList();
}
// This code is contributed by Arnab Kundu
Java
// Java implementation of the approach
class LinkedList {
// Head of list
Node head;
// Linked list Node
class Node {
int data;
Node next;
Node(int d)
{
data = d;
next = null;
}
}
// Function to delete the nth node from
// the end of the given linked list
void deleteNode(int key)
{
// First pointer will point to
// the head of the linked list
Node first = head;
// Second pointer will point to the
// Nth node from the beginning
Node second = head;
for (int i = 0; i < key; i++) {
// If count of nodes in the given
// linked list is <= N
if (second.next == null) {
// If count = N i.e. delete the head node
if (i == key - 1)
head = head.next;
return;
}
second = second.next;
}
// Increment both the pointers by one until
// second pointer reaches the end
while (second.next != null) {
first = first.next;
second = second.next;
}
// First must be pointing to the
// Nth node from the end by now
// So, delete the node first is pointing to
first.next = first.next.next;
}
// Function to insert a new Node at front of the list
public void push(int new_data)
{
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}
// Function to print the linked list
public void printList()
{
Node tnode = head;
while (tnode != null) {
System.out.print(tnode.data + " ");
tnode = tnode.next;
}
}
// Driver code
public static void main(String[] args)
{
LinkedList llist = new LinkedList();
llist.push(7);
llist.push(1);
llist.push(3);
llist.push(2);
System.out.println("\nCreated Linked list is:");
llist.printList();
int N = 1;
llist.deleteNode(N);
System.out.println("\nLinked List after Deletion is:");
llist.printList();
}
}
Python3
# Python3 implementation of the approach
class Node:
def __init__(self, new_data):
self.data = new_data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
# createNode and and make linked list
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
def deleteNode(self, n):
first = self.head
second = self.head
for i in range(n):
# If count of nodes in the
# given list is less than 'n'
if(second.next == None):
# If index = n then
# delete the head node
if(i == n - 1):
self.head = self.head.next
return self.head
second = second.next
while(second.next != None):
second = second.next
first = first.next
first.next = first.next.next
def printList(self):
tmp_head = self.head
while(tmp_head != None):
print(tmp_head.data, end = ' ')
tmp_head = tmp_head.next
# Driver Code
llist = LinkedList()
llist.push(7)
llist.push(1)
llist.push(3)
llist.push(2)
print("Created Linked list is:")
llist.printList()
llist.deleteNode(1)
print("\nLinked List after Deletion is:")
llist.printList()
# This code is contributed by RaviParkash
C#
// C# implementation of the approach
using System;
public class LinkedList
{
// Head of list
public Node head;
// Linked list Node
public class Node
{
public int data;
public Node next;
public Node(int d)
{
data = d;
next = null;
}
}
// Function to delete the nth node from
// the end of the given linked list
void deleteNode(int key)
{
// First pointer will point to
// the head of the linked list
Node first = head;
// Second pointer will point to the
// Nth node from the beginning
Node second = head;
for (int i = 0; i < key; i++)
{
// If count of nodes in the given
// linked list is <= N
if (second.next == null)
{
// If count = N i.e. delete the head node
if (i == key - 1)
head = head.next;
return;
}
second = second.next;
}
// Increment both the pointers by one until
// second pointer reaches the end
while (second.next != null)
{
first = first.next;
second = second.next;
}
// First must be pointing to the
// Nth node from the end by now
// So, delete the node first is pointing to
first.next = first.next.next;
}
// Function to insert a new Node at front of the list
public void push(int new_data)
{
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}
// Function to print the linked list
public void printList()
{
Node tnode = head;
while (tnode != null)
{
Console.Write(tnode.data + " ");
tnode = tnode.next;
}
}
// Driver code
public static void Main(String[] args)
{
LinkedList llist = new LinkedList();
llist.push(7);
llist.push(1);
llist.push(3);
llist.push(2);
Console.WriteLine("\nCreated Linked list is:");
llist.printList();
int N = 1;
llist.deleteNode(N);
Console.WriteLine("\nLinked List after Deletion is:");
llist.printList();
}
}
// This code is contributed by 29AjayKumar
Javascript
C++
// C++ implementation of the approach
// Code is contributed by Paras Saini
#include
using namespace std;
class LinkedList {
public:
int val;
LinkedList* next;
LinkedList()
{
this->next = NULL;
this->val = 0;
}
LinkedList(int val)
{
this->next = NULL;
this->val = val;
}
LinkedList* addNode(int val)
{
if (this == NULL) {
return new LinkedList(val);
}
else {
LinkedList* ptr = this;
while (ptr->next) {
ptr = ptr->next;
}
ptr->next = new LinkedList(val);
return this;
}
}
void removeNthNodeFromEndHelper(LinkedList* head,
int& n)
{
if (!head)
return;
// Adding the elements in the recursion
// stack
removeNthNodeFromEndHelper(head->next, n);
// Popping the elements from recursion stack
n -= 1;
// If we reach the previous of target node
if (n == -1){
LinkedList* temp = head->next;
head->next = head->next->next;
free (temp);
}
}
LinkedList* removeNthNodeFromEnd(int n)
{
// return NULL if we have NULL head or only
// one node.
if (!this or !this->next)
return NULL;
// Create a dummy node and point its next to
// head.
LinkedList* dummy = new LinkedList();
dummy->next = this;
// Call function to remove Nth node from end
removeNthNodeFromEndHelper(dummy, n);
// Return new head i.e, dummy->next
return dummy->next;
}
void printLinkedList()
{
if (!this) {
cout << "Empty List\n";
return;
}
LinkedList* ptr = this;
while (ptr) {
cout << ptr->val << " ";
ptr = ptr->next;
}
cout << endl;
}
};
class TestCase {
private:
void printOutput(LinkedList* head)
{
// Output:
if (!head)
cout << "Empty Linked List\n";
else
head->printLinkedList();
}
void testCase1()
{
LinkedList* head = new LinkedList(1);
head = head->addNode(2);
head = head->addNode(3);
head = head->addNode(4);
head = head->addNode(5);
head->printLinkedList(); // Print: 1 2 3 4 5
head = head->removeNthNodeFromEnd(2);
printOutput(head); // Output: 1 2 3 5
}
void testCase2()
{
// Important Edge Case, where linkedList [1]
// and n=1,
LinkedList* head = new LinkedList(1);
head->printLinkedList(); // Print: 1
head = head->removeNthNodeFromEnd(2);
printOutput(head); // Output: Empty Linked List
}
void testCase3()
{
LinkedList* head = new LinkedList(1);
head = head->addNode(2);
head->printLinkedList(); // Print: 1 2
head = head->removeNthNodeFromEnd(1);
printOutput(head); // Output: 1
}
public:
void executeTestCases()
{
testCase1();
testCase2();
testCase3();
}
};
int main()
{
TestCase testCase;
testCase.executeTestCases();
return 0;
}
Created Linked list is:
2 3 1 7
Linked List after Deletion is:
2 3 1
我们已经涵盖了上面的迭代版本,
现在让我们也看看它的递归方法,
递归方法:
1)创建一个虚拟节点并创建一个从虚拟节点到头节点的链接。即,dummy->next = head
2) 然后我们将使用递归堆栈来跟踪在递归调用中被压入的元素。
3) 在从递归栈中弹出元素时,我们将递减 N(目标节点从链表末尾的位置),即 N = N-1。
4) 当我们到达 (N==0) 时,表示我们已经到达目标节点,
5)但这里有一个问题,要删除目标节点,我们需要它的前一个节点,
6) 所以我们现在将在 (N==-1) 时停止,即我们到达前一个节点。
7)现在通过使用previousNode->next = previousNode->next->next来删除节点非常简单。
C++
// C++ implementation of the approach
// Code is contributed by Paras Saini
#include
using namespace std;
class LinkedList {
public:
int val;
LinkedList* next;
LinkedList()
{
this->next = NULL;
this->val = 0;
}
LinkedList(int val)
{
this->next = NULL;
this->val = val;
}
LinkedList* addNode(int val)
{
if (this == NULL) {
return new LinkedList(val);
}
else {
LinkedList* ptr = this;
while (ptr->next) {
ptr = ptr->next;
}
ptr->next = new LinkedList(val);
return this;
}
}
void removeNthNodeFromEndHelper(LinkedList* head,
int& n)
{
if (!head)
return;
// Adding the elements in the recursion
// stack
removeNthNodeFromEndHelper(head->next, n);
// Popping the elements from recursion stack
n -= 1;
// If we reach the previous of target node
if (n == -1){
LinkedList* temp = head->next;
head->next = head->next->next;
free (temp);
}
}
LinkedList* removeNthNodeFromEnd(int n)
{
// return NULL if we have NULL head or only
// one node.
if (!this or !this->next)
return NULL;
// Create a dummy node and point its next to
// head.
LinkedList* dummy = new LinkedList();
dummy->next = this;
// Call function to remove Nth node from end
removeNthNodeFromEndHelper(dummy, n);
// Return new head i.e, dummy->next
return dummy->next;
}
void printLinkedList()
{
if (!this) {
cout << "Empty List\n";
return;
}
LinkedList* ptr = this;
while (ptr) {
cout << ptr->val << " ";
ptr = ptr->next;
}
cout << endl;
}
};
class TestCase {
private:
void printOutput(LinkedList* head)
{
// Output:
if (!head)
cout << "Empty Linked List\n";
else
head->printLinkedList();
}
void testCase1()
{
LinkedList* head = new LinkedList(1);
head = head->addNode(2);
head = head->addNode(3);
head = head->addNode(4);
head = head->addNode(5);
head->printLinkedList(); // Print: 1 2 3 4 5
head = head->removeNthNodeFromEnd(2);
printOutput(head); // Output: 1 2 3 5
}
void testCase2()
{
// Important Edge Case, where linkedList [1]
// and n=1,
LinkedList* head = new LinkedList(1);
head->printLinkedList(); // Print: 1
head = head->removeNthNodeFromEnd(2);
printOutput(head); // Output: Empty Linked List
}
void testCase3()
{
LinkedList* head = new LinkedList(1);
head = head->addNode(2);
head->printLinkedList(); // Print: 1 2
head = head->removeNthNodeFromEnd(1);
printOutput(head); // Output: 1
}
public:
void executeTestCases()
{
testCase1();
testCase2();
testCase3();
}
};
int main()
{
TestCase testCase;
testCase.executeTestCases();
return 0;
}
1 2 3 4 5
1 2 3 5
1
Empty Linked List
1 2
1
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。