# 19. Delete the penultimate node of the linked list

## subject

Give you a linked list, delete the penultimate node of the linked list, and return the head node of the linked list.

Input: head = [1,2,3,4,5], n = 2

Output: [1,2,3,5]

Example 2:

Input: head = [1], n = 1

Output: []

Example 3:

Input: head = [1,2], n = 1

Output: [1]

Tips:

The number of nodes in the linked list is sz

1 <= sz <= 30

0 <= Node.val <= 100

1 <= n <= sz

Source: LeetCode

Link: https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list

The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

## Problem solving - violence

To delete a node in the linked list, you need to know its previous node. For the head node, there is no previous node. Therefore, the virtual head node dummy needs to be defined

The x-th node of the linked list must be traversed.

The first traversal knows the length of the whole linked list, and converts the reciprocal node into the x-th node of the positive number

The second traversal deletes the penultimate node

ListNode dummy = new ListNode(); //Add a node without data to unify the boundary node operation dummy.next = head; int count = 1; while(head.next!=null){ head = head.next; count++; } n = count - n + 1;//Delete nth from beginning to end count = 1; ListNode pre = dummy; head = dummy.next; for(;count!=n;count++){ pre=head; head = head.next; }//Found element to delete //Delete pre.next = head.next; return dummy.next;

## Problem solving - hash table

Can you try using one scan implementation?

The second traversal is mainly to find the elements to be deleted, so if we use the hash table to record the location information at the first traversal, we don't need to traverse again.

class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummy = new ListNode(); dummy.next = head; HashMap<Integer,ListNode> map = new HashMap<>(); int count = 0; map.put(count,dummy); while(head!=null){ count++; map.put(count,head); head = head.next; } //Calculate the location of the deleted element n = count-n+1; //Gets the previous element and the current element of the element to be deleted ListNode pre = map.get(n-1); head = map.get(n); pre.next = head.next; return dummy.next; } }

## Problem solving - double pointer

The previous linked list questions used double pointers. Here we consider double pointers. Double pointers are suitable for dividing intervals, distances, etc.

The main reason why you need to traverse is to find the length of the linked list, that is, you need to traverse to the back of the last node, and then locate the reciprocal node through the back of the last node. Here, we can use a pointer to point to the last node and a pointer to the previous node to be deleted.

The node to be deleted here is the penultimate node in the linked list. slow points to the previous node of the node to be deleted.

How to determine the position of slow? When the pointer fast points to null, there is a difference of 2 nodes between it and the pointer slow, which is exactly n=2.

Let fast take n+1 steps first, and then go together

class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummyHead = new ListNode(0); dummyHead.next = head; // The slow pointer initially points to the virtual header node ListNode slow = dummyHead; // The fast pointer initially points to the virtual header node ListNode fast = dummyHead; // The fast pointer moves forward n+1 steps first for(int i = 0; i <= n; i++) { fast = fast.next; } // The fast and slow pointers move forward at the same time until the fast pointer points to null while (fast!=null){ fast = fast.next; slow = slow.next; } // The next node of the slow pointer is the node to be deleted ListNode delNode = slow.next; // The subsequent pointer of the slow pointer points to the next node of the node to be deleted // In this way, the node to be deleted is deleted slow.next = delNode.next; delNode.next = null; return dummyHead.next; } }