【LeetCode】Linked List Reversal

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:
insert image description here
As shown in the figure. Let's analyze what we need to think about if we want to complete the flip:

  1. Loop through all nodes until the end. So you need to confirm the end condition
  2. 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)
    insert image description here

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 whileloop. 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 currNodeto represent the current operation node, which moves backwards with the traversal depth. Obviously its initial value is headthe head node, so it can be used currNode == nullto 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:

  1. Record the original next pointing node of the current node, which is recorded here oldNextNode(see the above figure for the reason)
  2. A precursor node is also needed preNodeto 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.
insert image description here
Steps:

  1. set oldNextNodeto currNodethe next node
  2. Point currNodethe next node ofpreNode
  3. preNodeSet ascurrNode
  4. currNodeSetting it to oldNextNode
    insert image description here
    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:
insert image description here
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:
insert image description here
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 preNodestate 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:
insert image description here
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:

  1. 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)
  2. After obtaining the node returned by the recursive call recursion , use recursion .next = curr; curr.next = null;it
    insert image description here

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:
insert image description here

Guess you like

Origin blog.csdn.net/qq_32681589/article/details/132032647