Linked list problem, how to deliver the turtle gracefully?

Posted by manchuwok on Tue, 01 Feb 2022 13:24:15 +0100

preface

Hello, I'm "programmer bear" from Huawei. Most children's shoes know that when solving problems related to "linked list", the commonly used problem-solving routines mainly include "double pointer", "iteration" and "virtual head node".

Today, "Little Bear" introduces the strategy of using "recursion" to kill the related problems of "linked list" to make the code more "elegant". Two common interview questions are used as examples for your reference and hope to be helpful to you.

Linked list and recursion

Linked list has natural recursion. A linked list can see the head node and then connect a shorter linked list. This shorter linked list takes the next node of the head node of the original linked list as the head node and pushes it inward in turn until the last shorter linked list is empty. Empty itself is also a linked list (the most basic).

Take single linked list 1 - > 2 - > 3 - > null as an example, as shown in the following figure:

Original linked list

See the head node 1 of the original linked list and hang a shorter linked list

Continue disassembly until disassembly is impossible

With such thinking, many problems related to "linked list" can be solved by using the idea of "recursion".

Sword finger Offer 24 Reverse linked list

Define a function, input the head node of a linked list, invert the linked list and output the head node of the inverted linked list.
 

Examples:

input: 1->2->3->4->5->NULL
 output: 5->4->3->2->1->NULL
 

Restrictions:
0 <= Number of nodes <= 5000

Problem solving ideas

To reverse the linked list, that is, the head node of the original linked list becomes the tail node of the new linked list, and the tail node of the original linked list becomes the head node of the new linked list. As shown below:

Before reversing:

After reversal:

The main strategies are as follows: 1. Modify the value of the linked list. As shown in the figure above, change the value 1 of the original chain header node to the value 3 of the original chain tail node, and so on; 2. Let's traverse the whole linked list, let the tail node of the linked list point to its previous node, and so on.

Although both strategies are feasible, strategy 2 is usually required in interviews.

From the above "recursion and linked list", we can also use the "recursion method" to solve this problem.

How to solve it through "recursion"? See the example below.

"Example"

Linked list 1 - > 2 - > 3 - > null is an example, as shown in the following figure.

Constantly traverse to find the original linked list as the tail node, that is, the head node of the new linked list.

Then let the tail node point to its predecessor node, and so on.

The detailed steps are as follows:

Show me the Code

「C」

struct ListNode* reverseList(struct ListNode* head){
    /* Recursive termination condition*/
    if (head == NULL || head->next == NULL) {
        return head;
    }

    /* Reverse the current linked list node*/
    struct ListNode* newHead = reverseList(head->next);

    /* The tail node of the original linked list points to its predecessor node one by one*/
    head->next->next = head;

    /* Prevent ring formation*/
    head->next = NULL;

    /* Returns the new chain header node*/
    return newHead;
}

「java」

ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }

    ListNode node = reverseList(head.next);
    head.next.next = head;
    head.next = null;

    return node;
}

Of course, this problem can also be done by "iteration", and its code (python version) is also very elegant, as follows:

Show me the Code

「python」

def reverseList(self, head: ListNode) -> ListNode:
    cur, pre = head, None
    while cur:
        cur.next, pre, cur = pre, cur, cur.next
        
    return pre 

"Complexity analysis"

Time complexity: "O(n)", where n is the length of the linked list. Each node of the linked list is reversed.

Spatial complexity: "O(n)", where n is the length of the linked list. Stack space for recursive calls, up to N layers.

203. Remove linked list elements

Give you a head node of the linked list head And an integer val ,Please delete all items in the linked list 

Node.val == val And return New header node . 

Examples 1: 

Input: head = [1,2,6,3,4,5,6], val = 6
 Output:[1,2,3,4,5]

Examples 2: 

Input: head = [], val = 1
 Output:[]

Examples 3: 

Input: head = [7,7,7,7], val = 7
 Output:[]

Problem solving ideas

To remove a node with a given value from the linked list, the general strategy is to "find the precursor node of the node with a given value, and then point it to the successor node of the node with a given value".

For example, to delete a node with a value of 3 in the linked list 1 - > 2 - > 3 - > null, you must first find its predecessor node (the node with a value of 2), as shown in the following figure:

From the above "recursion and linked list", we can also use the "recursion method" to solve this problem, constantly delete the nodes with a given value in the shorter linked list, and then connect the processed shorter linked list to its predecessor node.

"Note" finally, judge whether the head node of the original linked list is the node to be removed.

"Example"

Taking the linked list 1 - > 2 - > 3 - > null as an example, the process of removing the node of the given value in the linked list is shown in the following figure.

Show me the Code

「C++」

ListNode* removeElements(ListNode* head, int val) {
    /* Recursive termination condition*/
    if(head == NULL) {
        return NULL;
    }

    /* The node of the element whose value is val after deleting the head node in the linked list*/
    head->next=removeElements(head->next,val);

    /* Judge whether the header node is a node with a value of val , and then return*/
    return head->val==val ? head->next : head;
}

「Golang」

func removeElements(head *ListNode, val int) *ListNode {
    if head == nil {
        return head
    }

    head.Next = removeElements(head.Next, val)
    if head.Val == val {
        return head.Next
    }

    return head
}

"Complexity analysis"

Time complexity: "O(n)", where n is the length of the linked list. Recursion needs to traverse the linked list once.

Spatial complexity: "O(n)", where n is the length of the linked list. Recursive call stack, no more than N layers.

Wonderful review of previous periods

How many people really know recursion?

Binary search application --- single element in ordered array

Fast and slow pointer --- doesn't it mean that the fast pointer takes two steps and the slow pointer takes one step?

Multiple ideas spike the longest palindrome substring of classic interview questions

Hand tear Tencent interview questions - Product maximum subarray

More wonderful

Pay attention to the official account "programmer bear"

WeChat official account

Topics: Algorithm data structure Interview linked list recursion