Introduction to linked list algorithm questions and summary of ideas (including understanding and use of recursive method)

Part of the content comes from https://www.programmercarl.com/

0 Preface

Linked list is a very basic data structure, which is simpler than traditional array structure in terms of deletion and insertion.

1. Linked list infrastructure

1.1 What is a linked list?

A linked list is a linear structure connected in series through pointers. Each node is composed of two parts, one is the data field and the other is the pointer field (which stores the pointer to the next node). The pointer field of the last node points to null (null pointer). the meaning of).

The entry node of the link is called the head node of the linked list, which is also the head.

1.2 Linked list classification

  • Single list. That is, there is only one pointer to the next node.

  • Double linked list. Each node has two pointer fields, one pointing to the next node and one pointing to the previous node.

  • Circular linked list. The linked list is connected end to end.

1.3 Linked list storage method

Arrays are continuously distributed in memory, but linked lists are not continuously distributed in memory.

A linked list links nodes in memory through pointers in the pointer field.

Therefore, the nodes in the linked list are not continuously distributed in the memory, but scattered at certain addresses in the memory. The allocation mechanism depends on the memory management of the operating system.

2. Common ideas for linked list questions

2.1 Double pointer method

In the linked list problem, you can also consider the double pointer method.

2.2 Recursive method

Linked lists are particularly suitable for using recursive algorithms, because many linked list algorithm questions require judging nodes one by one. When encountering this type of problem, you can consider the recursive method.

Below is a relatively general recursive code template. Different from other recursive tutorials, this process is highly targeted and can be easily incorporated into the questions. The specific process and code are as follows.

First of all, we must clarify the recursive process. During the operation of the linked list recursive function, it is mainly divided into three parts. 1. Each node enters the recursive function in turn, 2. Returns after encountering boundary conditions, 3. Returns all the way to the starting point of the recursion.

Next, for the above process, the recursive code will be decomposed and explained.

First of all, before writing, first determine which part of the 13 processes in the above three parts needs to be logically processed.

  • In process 1, logical processing needs to be performed, and from beginning to end, every time a recursive function is entered, a logical processing will be performed. At this time, the processing logic code must be written before the recursive function. If you want to pass the result of this processing to subsequent nodes, you can set the variable to the variable of the recursive function and pass it, so that the logical function will be run before each subsequent recursion, and the result will be passed later.
  • Logical processing is performed in the 3 process, that is, logical processing is performed from back to front. At this time, the logic code should be written after the recursive function and before the return value. If you want to pass the result of each processing to the previous node, you can set the node as the return value at this time, so that after each recursive function runs, the logic code will be run and the return value will be returned.

Secondly, after determining the logical code process, you can actually start writing the code. The first step is to write the exit condition. In the linked list, it will show that the current node is empty, that is, it has reached the end.

Finally, complete the logic code determined at the beginning to complete the writing of the entire recursive function.

func help(head *ListNode,n int)int{
    //停止条件
    if head==nil{
        return n,false,nil
    }
    //往下递归前做的事情,n为往下传入的值
    num:=help(head.Next,n)
    //递归返回时做的事情
    if num==0{
      //做一些处理
    }
    return num //向上传递
    }

1.1 Question training

1.1.1 Reverse linked list

206. Reverse linked list - LeetCode

Solution

According to the above logic, two methods can be used, one is to perform logical processing in the first part (from front to back), and the other is to perform logical processing in the third part (from back to front).

When performing logical processing in the first part, we must first save the address of the next node after the currently traversed node, because the address cannot be found after reversal. Then perform normal reversal, the code is as follows.

The third part is more troublesome when performing logical processing. When reversing first, we need the address of the previous node, and passing from front to back can only be passed as a variable of the recursive function, so we set one of the variables of the recursive function to pre , to pass. Then we also need to return the last node, and the value passed from the last node forward needs to be passed as the return value, so we can set a return value, the code is as follows.

Code

//从前往后的逻辑处理
func reverseList(head *ListNode) *ListNode {
    return help(nil, head)
}

func help(pre, head *ListNode)*ListNode{
    if head == nil {
        return pre
    }
    next := head.Next
    head.Next = pre
    return help(head, next)
}

//从后往前的逻辑处理
func reverseList(head *ListNode) *ListNode {

    return help(head,nil)
}

func help(head *ListNode,pre *ListNode)*ListNode{
    if head==nil{
    return nil
    }
    result:=help(head.Next,head)
    if head.Next==nil{
        result=head
    }
    head.Next=pre
    return result
}

2.3 Iterative method

Using the iterative method, each node can be quickly judged and operated.

2.4 Virtual header node

A big problem with linked lists is that to operate the current node, you must find the previous node. This causes the embarrassment of the head node, because the head node has no previous node. Each situation corresponding to the head node must be handled separately, so using the technique of virtual head nodes can solve this problem .

Guess you like

Origin blog.csdn.net/doreen211/article/details/125745288
Recommended