topic
Title: Given the head node of a singly linked list, reverse the link order of the singly linked list
Example:
Input: 1->2->3->4->5
Output: 5->4->3->2->1
Requirements : implemented in two ways
Solution
Method 1: (direct iteration method)
train of thought
The structure of a singly linked list is as follows:
As shown in the figure. Let's analyze what we need to think about if we want to complete the flip:
- Loop through all nodes until the end. So you need to confirm the end condition
- Safely point the current node to its predecessor node (directly pointing to it will cause the linked list traversal to fail, as shown below, the next operation node cannot be found)
For the first point, since you want to loop through, it is nothing more than an iterator or a loop. Obviously there is no way to use an iterator here, so consider using a while
loop. When will it end? It is not difficult to find that it is [when the next node of the current node is null], or we add a new node currNode
to represent the current operation node, which moves backwards with the traversal depth. Obviously its initial value is head
the head node, so it can be used currNode == null
to indicate the end of traversal.
For point 2, how can the current node point to its predecessor node safely? Normally, the following 2 steps are required to ensure:
- Record the original next pointing node of the current node, which is recorded here
oldNextNode
(see the above figure for the reason) - A precursor node is also needed
preNode
to record the precursor node that needs to be set for the next node (you can also see the above figure, except that the next node cannot be found, in fact, the next node cannot find the previous node, so it also needs to be recorded)
When we are ready we can try the simulation.
Steps:
- set
oldNextNode
tocurrNode
the next node - Point
currNode
the next node ofpreNode
preNode
Set ascurrNode
currNode
Setting it tooldNextNode
seems to be ok, so let's start writing code
code example
code show as below:
public class ReverseLinkedList {
public static void main(String[] args) {
ListNode node5 = new ListNode(5, null);
ListNode node4 = new ListNode(4, node5);
ListNode node3 = new ListNode(3, node4);
ListNode node2 = new ListNode(2, node3);
ListNode node1 = new ListNode(1, node2);
reverseLinkedList(node1);
}
private static void reverseLinkedList(ListNode head) {
// 初始化我们的中间节点
ListNode currNode = head;
ListNode oldNextNode = null;
ListNode preNode = null;
// 循环遍历,currNode != null 则表示还没遍历到结尾
while (currNode != null) {
oldNextNode = currNode.next;
currNode.next = preNode;
preNode = currNode;
currNode = oldNextNode;
}
System.out.println("试试看");
System.out.println(preNode);
}
}
Finally, let's see the result:
it's upside down!
Method 2: (recursive method)
train of thought
(PS: Since it is said that it is solved by recursion, we must first know what recursion can do. It can be said that any problem that can be solved by recursion must be able to divide a big problem into N small ones with commonality question. So, we can look in that direction.)
Still looking at the structure diagram of the singly linked list:
we found that if we start from the last node, the problem of this topic will become another problem:Who is my precursor node?
In normal traversal, we use preNode
state nodes to keep track of predecessor nodes, but in recursion it's less of a hassle! Because when recursively traversing nodes forward, the end of the current node must be at the calling place of the predecessor node. The effect diagram is as follows:
the recursive code is as follows:
public static void main(String[] args) {
ListNode node5 = new ListNode(5, null);
ListNode node4 = new ListNode(4, node5);
ListNode node3 = new ListNode(3, node4);
ListNode node2 = new ListNode(2, node3);
ListNode node1 = new ListNode(1, node2);
// reverseLinkedList(node1);
recursion(node1);
}
private static ListNode recursion(ListNode curr) {
// 递归出口(遍历到最后了)
if (curr == null || curr.next == null) {
return curr;
}
ListNode recursion = recursion(curr.next);
System.out.println(recursion.value);
return curr;
}
// 系统输出:
// 5
// 4
// 3
// 2
Now that we know this feature, we only need to do the following steps:
- Each recursive call returns the current node (this is to create an environment where the current node can be in the same code block as the predecessor node)
- After obtaining the node returned by the recursive call
recursion
, userecursion .next = curr; curr.next = null;
it
code example
public static void main(String[] args) {
ListNode node5 = new ListNode(5, null);
ListNode node4 = new ListNode(4, node5);
ListNode node3 = new ListNode(3, node4);
ListNode node2 = new ListNode(2, node3);
ListNode node1 = new ListNode(1, node2);
// reverseLinkedList(node1);
recursion(node1);
System.out.println(node5);
}
private static ListNode recursion(ListNode curr) {
// 递归出口(遍历到最后了)
if (curr == null || curr.next == null) {
return curr;
}
ListNode recursion = recursion(curr.next);
recursion.next = curr;
curr.next = null;
return curr;
}
Finally, let's look at the result: