Delete the Last Node of a Linked List
Solve this Problem
Given the
head of a singly linked list, delete the last node and return the head of the resulting list. If the list is empty or has just one node, the result is an empty list.
Unlike deleting the first node, this one still requires a walk from head — a singly linked list keeps no pointer to its own tail, so the second-to-last node has to be found by checking one node ahead at each step (curr.next.next == null). Once found, dropping the last node is a single pointer write.
Test Case 1:
Input:head = [3, 8, 5, 1]
Output:[3, 8, 5]
Explanation:The last node (1) is removed.
Test Case 2:
Input:head = [9]
Output:[]
Explanation:Deleting the only node leaves an empty list — it was both the first and last node.
Test Case 3:
Input:head = []
Output:[]
Explanation:Nothing to delete — the empty list stays empty.
Constraints
- ◆
0 ≤ number of nodes in head ≤ 10⁴ - ◆
-10⁹ ≤ node value ≤ 10⁹ - ◆
Handle the empty list and the single-node list — both must return an empty list
🚀
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
🧪Try your own test case
| 1 | class Solution { |
| 2 | public Node deleteAtEnd(Node head) { |
| 3 | if (head == null || head.next == null) { |
| 4 | return null; |
| 5 | } |
| 6 | Node curr = head; |
| 7 | while (curr.next.next != null) { |
| 8 | curr = curr.next; |
| 9 | } |
| 10 | curr.next = null; |
| 11 | return head; |
| 12 | } |
| 13 | } |
| 14 |
3
8
5
1
Variables
head
3COMPARE
head and head.next are both non-null, so skip the base cases and walk to find the second-to-last node.
Step 1 / 6
Approach & Solutions
Brute Force — Copy to Array Except the Last Node, Rebuild List
BruteWalk the entire list into a plain array, then drop its last element. Throw the original list away and build a brand-new list from that array using a dummy + tail pointer. Correct, but it re-allocates n - 1 nodes just to drop one from the end.
Time
O(n)Space
O(n)Java
1// Node definition used in this problem:
2// class Node {
3// int val;
4// Node next;
5// }
6
7class Solution {
8 public Node deleteAtEnd(Node head) {
9 List<Integer> vals = new ArrayList<>();
10 Node curr = head;
11 while (curr != null) {
12 vals.add(curr.val);
13 curr = curr.next;
14 }
15 if (!vals.isEmpty()) {
16 vals.remove(vals.size() - 1);
17 }
18 Node dummy = new Node(0);
19 Node tail = dummy;
20 for (int v : vals) {
21 tail.next = new Node(v);
22 tail = tail.next;
23 }
24 return dummy.next;
25 }
26}Optimal — Traverse to the Second-to-Last Node, Snip the Tail
OptimalA singly linked list has no pointer to its own tail, so the second-to-last node still has to be found by walking from head — but once found, deleting the last node is a single pointer write. Handle the empty list and the single-node list separately: both simply return null.
Time
O(n)Space
O(1) extraJava
1// Node definition used in this problem:
2// class Node {
3// int val;
4// Node next;
5// }
6
7class Solution {
8 public Node deleteAtEnd(Node head) {
9 if (head == null || head.next == null) {
10 return null;
11 }
12 Node curr = head;
13 while (curr.next.next != null) {
14 curr = curr.next;
15 }
16 curr.next = null;
17 return head;
18 }
19}