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

77 阅读9分钟

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

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

例子:

输入:2 -> 3 -> 1 -> 7 -> NULL,N = 1
输出:
创建的链表为:
2 3 1 7
删除后的链表为:
2 3 1

输入:1 -> 2 -> 3 -> 4 -> NULL,N = 4
输出:
创建的链表为:
1 2 3 4
删除后的链表为:
2 3 4

设 K 为链表中的总节点数。
观察:从末尾算起的第 N 个节点是从开头算起的第 (K-N+1) 个节点。
所以问题就简化为我们必须从头开始找到第 (K-N+1) 个节点。

  • 一种方法是在一次遍历中找到链表的长度 (K),然后在第二次遍历中从头开始移动 (K-N+1) 步,到达从末尾算起的第 N 个节点。

C++

// C++ code for the deleting a node from end
// in two traversal
#include <bits/stdc++.h>
using namespace std;
 
struct Node {
    int data;
    struct Node* next;
    Node(int value)
    {
        this->data = value;
        this->next = NULL;
    }
};
 
int length(Node* head)
{
    Node* temp = head;
    int count = 0;
    while (temp != NULL) {
        count++;
        temp = temp->next;
    }
    return count;
}
 
void printList(Node* head)
{
    Node* ptr = head;
    while (ptr != NULL) {
        cout << ptr->data << " ";
        ptr = ptr->next;
    }
    cout << endl;
}
 
Node* deleteNthNodeFromEnd(Node* head, int n)
{
    int Length = length(head);
    int nodeFromBeginning = Length - n + 1;
    Node* prev = NULL;
    Node* temp = head;
    for (int i = 1; i < nodeFromBeginning; i++) {
        prev = temp;
        temp = temp->next;
    }
    if (prev == NULL) {
        head = head->next;
        return head;
    }
    else {
        prev->next = prev->next->next;
        return head;
    }
}
 
int main()
{
    Node* head = new Node(1);
    head->next = new Node(2);
    head->next->next = new Node(3);
    head->next->next->next = new Node(4);
    head->next->next->next->next = new Node(5);
    cout<<"Linked List before Deletion:"<<endl;
    printList(head);
 
    head = deleteNthNodeFromEnd(head, 4);
 
      cout<<"Linked List after Deletion: "<<endl;
    printList(head);
    return 0;
}
 

Java

class Node {
  int data;
  Node next;
 
  Node(int value)
  {
    this.data = value;
    this.next = null;
  }
}
 
class Main {
  static int length(Node head)
  {
    Node temp = head;
    int count = 0;
    while (temp != null) {
      count++;
      temp = temp.next;
    }
    return count;
  }
 
  static void printList(Node head)
  {
    Node ptr = head;
    while (ptr != null) {
      System.out.print(ptr.data + " ");
      ptr = ptr.next;
    }
    System.out.println();
  }
 
  static Node deleteNthNodeFromEnd(Node head, int n)
  {
    int Length = length(head);
    int nodeFromBeginning = Length - n + 1;
    Node prev = null;
    Node temp = head;
    for (int i = 1; i < nodeFromBeginning; i++) {
      prev = temp;
      temp = temp.next;
    }
    if (prev == null) {
      head = head.next;
      return head;
    }
    else {
      prev.next = prev.next.next;
      return head;
    }
  }
 
  public static void main(String[] args)
  {
    Node head = new Node(1);
    head.next = new Node(2);
    head.next.next = new Node(3);
    head.next.next.next = new Node(4);
    head.next.next.next.next = new Node(5);
    System.out.println("Linked List before Deletion:");
    printList(head);
 
    head = deleteNthNodeFromEnd(head, 4);
 
    System.out.println("Linked List after Deletion:");
    printList(head);
  }
}
 

Python

# Python code for the deleting a node from end
# in two traversal
 
class Node:
    def __init__(self, value):
        self.data = value
        self.next = None
 
def length(head):
    temp = head
    count = 0
    while(temp != None):
        count += 1
        temp = temp.next
    return count
 
def printList(head):
    ptr = head
    while(ptr != None):
        print (ptr.data, end =" ")
        ptr = ptr.next
    print()
 
def deleteNthNodeFromEnd(head, n):
    Length = length(head)
    nodeFromBeginning = Length - n + 1
    prev = None
    temp = head
    for i in range(1, nodeFromBeginning):
        prev = temp
        temp = temp.next
    if(prev == None):
        head = head.next
        return head
    else:
        prev.next = prev.next.next
        return head
 
if __name__ == '__main__':
    head = Node(1)
    head.next = Node(2)
    head.next.next = Node(3)
    head.next.next.next = Node(4)
    head.next.next.next.next = Node(5)
    print("Linked List before Deletion:")
    printList(head)
 
    head = deleteNthNodeFromEnd(head, 4)
 
    print("Linked List after Deletion:")
    printList(head)

C#

// This C# code defines a class Node which represents a node
// in a linked list. Each node has an integer value 'data'
// and a reference to the next node in the list 'next'. The
// class also defines a static method 'Length' that takes
// the head of a linked list as input and returns the number
// of nodes in the list. Another static method 'PrintList'
// is defined to print the elements of a linked list.
 
using System;
 
public class Node {
    public int data; // data stored in the node
    public Node next; // reference to the next node
    // constructor to create a new node with the given data
    public Node(int value)
    {
        this.data = value;
        this.next = null;
    }
}
 
public class Program {
    // static method to find the length of a linked list
    // given its head node
    public static int Length(Node head)
    {
        Node temp = head;
        int count = 0;
        while (temp != null) // loop until the end of the
                             // list is reached
        {
            count++; // increment count for each node
                     // visited
            temp = temp.next; // move to the next node
        }
        return count;
    }
    // static method to print the elements of a linked list
    public static void PrintList(Node head)
    {
        Node ptr = head;
        while (ptr != null) // loop until the end of the
                            // list is reached
        {
            Console.Write(ptr.data
                          + " "); // print the data of the
                                  // current node
            ptr = ptr.next; // move to the next node
        }
        Console.WriteLine(); // move to the next line after
                             // printing the list
    }
 
    // static method to delete the nth node from the end of
    // a linked list
    public static Node DeleteNthNodeFromEnd(Node head,
                                            int n)
    {
        int Length = Program.Length(
            head); // find the length of the list
        int nodeFromBeginning
            = Length - n
              + 1; // find the index of the node to be
                   // deleted from the beginning
        Node prev = null;
        Node temp = head;
        for (int i = 1; i < nodeFromBeginning;
             i++) // loop until the node before the one to
                  // be deleted is reached
        {
            prev = temp;
            temp = temp.next;
        }
        if (prev
            == null) // if the first node is to be deleted
        {
            head = head.next; // update the head node to the
                              // next node
            return head; // return the updated head node
        }
        else // if any other node is to be deleted
        {
            prev.next
                = prev.next
                      .next; // skip the node to be deleted
                             // by updating the reference of
                             // the previous node
            return head; // return the head node
        }
    }
 
    public static void Main()
    {
        // create a linked list with 5 nodes
        Node head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(4);
        head.next.next.next.next = new Node(5);
 
        // print the linked list before deletion
        Console.WriteLine("Linked List before Deletion:");
        Program.PrintList(head);
 
        // delete the 4th node from the end of the linked
        // list
        head = Program.DeleteNthNodeFromEnd(head, 4);
 
        // print the linked list after deletion
        Console.WriteLine("Linked List after Deletion:");
        Program.PrintList(head);
    }
}

Javascript

class Node {
    constructor(value) {
        this.data = value;
        this.next = null;
    }
}
 
function length(head) {
    let temp = head;
    let count = 0;
    while (temp != null) {
        count++;
        temp = temp.next;
    }
    return count;
}
 
function printList(head) {
    let ptr = head;
    while (ptr != null) {
        process.stdout.write(ptr.data + " ");
        ptr = ptr.next;
    }
    console.log();
}
 
function deleteNthNodeFromEnd(head, n) {
    let Length = length(head);
    let nodeFromBeginning = Length - n + 1;
    let prev = null;
    let temp = head;
    for (let i = 1; i < nodeFromBeginning; i++) {
        prev = temp;
        temp = temp.next;
    }
    if (prev == null) {
        head = head.next;
        return head;
    } else {
        prev.next = prev.next.next;
        return head;
    }
}
 
let head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next = new Node(4);
head.next.next.next.next = new Node(5);
 
console.log("Linked List before Deletion:");
printList(head);
 
head = deleteNthNodeFromEnd(head, 4);
 
console.log("Linked List after Deletion:");
printList(head);

输出

Linked List before Deletion:
1 2 3 4 5 
Linked List after Deletion: 
1 3 4 5 

双指针方法:

  • 取两个指针;第一个将指向链表的头,第二个将指向从头开始的第 N 个节点。
  • 现在继续将两个指针同时加一,直到第二个指针指向链表的最后一个节点。
  • 经过上一步的操作,现在第一个指针应该指向倒数第N个节点。因此,删除第一个指针指向的节点。

下面是上述方法的实现:

C++

// C++ implementation of the approach
#include <bits/stdc++.h>
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
        // temporarily 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();
}
 

C

/* C program to merge two sorted linked lists */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
 
/* Link list node */
typedef struct Node {
    int data;
    struct Node* next;
} Node;
 
Node* deleteNode(Node* head, int key)
{
   
    // We will be using this pointer for holding address
    // temporarily 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 node at the beginning of the
linked list */
void push(Node** head_ref, int new_data)
{
    /* allocate node */
    Node* new_node = (Node*)malloc(sizeof(Node));
    /* put in the data */
    new_node->data = new_data;
    /* link the old list off the new node */
    new_node->next = (*head_ref);
    /* move the head to point to the new node */
    (*head_ref) = new_node;
}
 
/* Function to print nodes in a given linked list */
void printList(struct Node* node)
{
    while (node != NULL) {
        printf("%d ", node->data);
        node = node->next;
    }
}
 
// Driver program
int main()
{
    struct Node* head = NULL;
    push(&head, 7);
    push(&head, 1);
    push(&head, 3);
    push(&head, 2);
    printf("Created Linked list is:\n");
    printList(head);
    int n = 1;
    deleteNode(head, n);
    printf("\nLinked List after Deletion is:\n");
    printList(head);
    return 0;
}
 

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();
    }
}

Python

# 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 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()
 

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();
    }
}
 

Javascript

<script>
// javascript implementation of the approach
 
    // Head of list
    var head;
 
    // Linked list Node
    class Node {
        constructor(val) {
            this.data = val;
            this.next = null;
        }
    }
 
    // Function to delete the nth node from
    // the end of the given linked list
    function deleteNode(key) {
 
        // First pointer will point to
        // the head of the linked list
        var first = head;
 
        // Second pointer will point to the
        // Nth node from the beginning
        var second = head;
        for (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
     function push(new_data) {
        var new_node = new Node(new_data);
        new_node.next = head;
        head = new_node;
    }
 
    // Function to print the linked list
    function printList() {
        var tnode = head;
        while (tnode != null) {
            document.write(tnode.data + " ");
            tnode = tnode.next;
        }
    }
 
    // Driver code
     
        push(7);
        push(1);
        push(3);
        push(2);
 
        document.write("\nCreated Linked list is:<br/>");
        printList();
 
        var N = 1;
        deleteNode(N);
 
        document.write("<br/>Linked List after Deletion is:<br/>");
        printList();
 
</script>

输出

Created Linked list is:
2 3 1 7 
Linked List after Deletion is:
2 3 1 

时间复杂度:O(N),其中 N 是给定链表中的节点数。 辅助空间:O(1)