📌  相关文章
📜  从给定链表的末尾删除第 N 个节点

📅  最后修改于: 2022-05-13 01:57:44.016000             🧑  作者: Mango

从给定链表的末尾删除第 N 个节点

给定一个链表和一个整数N ,任务是从给定链表的末尾删除第N节点。

例子:

直觉:



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 现场工作专业课程学生竞争性编程现场课程