Linked list data structure and algorithm of learning methods Raiders

HowNet new sources of business, the original title: Questions articles | linked list data structures and algorithms of the series

 

Written on the front

If you, like deer and the beginning of the operation code linked list to achieve very ignorant, may wish to follow the deer after a month of time to sort out a summary of the list of questions and related operations, Deep proper exercise, I believe that when you true End practice these topics, not only let you down mentally confused on the list, but also for you to learn other data structures have great confidence and help!

As the article space totaling 8,000 words, to reduce the number of public version, the full version of the article please see the link at the bottom.

Study Advice

Deer do not recommend you to read all in one breath and exercises this topic, set himself a little planning, I had to finish the title, they both plan carefully every day to sort out a problem, to analyze each question thoroughly, so as to to achieve the best absorption.

Learning Path

Benpian divided into three stages, basic training stage, advanced stage exercises to strengthen the practice session.

1, basic training stage

First performed before the first stage, you have basic knowledge of the list to master, but for no hands wrote the code list, then you start from the most basic first stage. To ensure that every basis point to be hands-on with their own familiar language to write, although this blog entry are basically javascript code to achieve, but the idea of ​​the algorithm is static, if you encounter difficulties can own Baidu or Google, you can give me the bottom leave a message.

2, advanced practice phase

If you list above basic code has been completely mastered, then congratulations, you can be the next stage, advanced stage, this stage is to increase the difficulty of the operation is the actual list of problems to solve, so much exercise you analytical and problem solving skills, but also a test of your comprehensiveness, robustness of the code. This stage is very important, each of the following questions I have made a detailed analysis.

3, strengthen the practice phase

If these advanced stages of practice the kinds of questions you are well aware, then we might look real, LeetCode brought together many of the interview questions, so I put together a few classic topics at the top, you can try to answer them, related subject code and problem-solving ideas I have collated. This phase will be the subject of deer constantly updated in late you can master these problems, the list for you a piece of cake.

Phase One: basic training list

First, try to own the list one by one break below the most basic operation, the relevant code I also put together a good (first try to solve their own oh)

1, a single list of insert, delete, search operation (☛ title parsing)

2, circular list insert, delete, search operation (☛ title parsing)

3, two-way linked list insert, delete, search operation (☛ title parsing)

Phase II: Advanced Practice list

1, the print head from the end of the single chain

Title: Enter a list of the first node, in turn, print out the head from the tail value for each node.

1.1 Analysis and problem solving

▉ Analysis

1, the first thought is to see the topic list in reverse print output, a method of reversing the list, but this approach changed the original list structure.

※ disadvantage: that the changed list structure. If the list does not change the structure of how to solve?

2, can be drawn from the problem, we want to print the list from the tail to the head, under normal circumstances is printed from start to finish, we will think of the last data before printing, print data starting last, a kind of "last out "characteristics, we can think of a" stack "of such structures, with a stack to achieve.

※ drawback: the code simple enough.

※ advantages: robustness (in the case of uncertainty, the program can still be executed correctly).

3, referred to stack this data structure, we will think of "recursive" to achieve this is to use a stack data structure to achieve. Since the stack can be achieved, then the recursion can be achieved.

※ drawback: If the list is very long, very deep recursion depth, resulting in a stack overflow.

※ advantages: code is simple and straightforward.

▉ algorithm ideas

By the top of the problem analysis, the following solutions:

● reverse a linked list method

● stack implementation

● recursive

1, to achieve reverse list

From a content list output end of the head, the general idea is to list reversed, then the output data from beginning to end.

2, stack implementations

Single chain traversal from start to finish, in order to store the data onto the stack. Then traverse the entire stack, the print output data.

3, recursive

May be implemented in a recursive way by a single linked list output sequentially from the tail to the head, the recursive process involves "delivery" and "return", which inverts the output data list, the process loops using officially "handed", so the head of the output data start , then recursively used the "return" of the process to output content, the output current should first output node to the next node of the current node.

▉ test

Before writing the code, in order to write a good test case to improve the robustness of the code, but also to take into account the boundary cases, often the most deadly place the entire program, if we consider not comprehensive, there will be bug, causing the program to crash .

1, an input list empty;

2, only a list of the input node;

3, a plurality of input list nodes.

▉ code implementation

1, code implementation: inversion method list

1 // Define node

2 class  the Node {  . 3     constructor ( Data) {  . 4         . The this Data =  Data;  . 5         this.next =  null;  . 6}  . 7}  . 8 // defined list  . 9 class  the LinkedList { 10     constructor () { . 11         this.head the Node new new = ( 'head'); 12 is} 13 is 14     // function: single inverted list 15     @ steps: 16     @ 1, defined three pointers (pre = null / Next / Current) . 17     // 2, determines whether the list trans turn (head node is empty, whether a second node) 18     // 3, the tail pointer points to the first node Next . 19     //. 4, the tail pointer is moved forward20     // 5, the current pointer (Current) moves backward 21     @ 6, the one-turn head good junction point 22 is reverseList = () => { 23 is         // declare three pointers 24 Current = the let  this.head;  // current node pointer to the head 25 the let pre =  null; // tail pointer 26 is the let next; // pointer to the current pointer to the next 27 28         // determination conditions (a node more) single chain meets inverted? 29         IF ( this.head ==  null ||  this.head.next ==  null)  return  -1; 30 31 is         // begin reversing 32         the while (Current ==!  Null) { 33 is = current.next Next;34            current.next = pre;35            pre = current;36            current = next;37        }38        this.head = pre;39    }4041    //输出结点42    print = () =>{43        let currentNode = this.head44        //如果结点不为空45        while(currentNode !== null){46            console.log(currentNode.data)47            currentNode = currentNode.next;48        }49    }50}

2, code implementation: Stack cycle

1 // Method three: stack implementation

2 const = tailToHeadOutput (the currentNode) => {  . 3 the let  Stack = [];  . 4     // traverse the list, the data stack  . 5     the while {(the currentNode == null!)  . 6         stack.push (currentNode.data);  . 7 = the currentNode currentNode.next;  . 8}  . 9     // traverse the stack, the stack is 10     the while ( stack.length ==!  {0) . 11 Console. log ( stack.pop ()); 12 is} 13 is}

3, code for: recursion

1 // steps:

2 // 1, determines whether the list is empty  3 // 2, the termination condition (next node is empty)  4 // 3, the next printing node information recursively  . 5 const = tailToHeadOutput  ( head) => {  . 6     // determining whether the empty list  . 7     iF (head! ==  null) {  . 8         whether the next node is determined // empty  . 9         iF (head.next! ==  null) { 10             // next node is not empty, the first output next node . 11 tailToHeadOutput (head.next) 12 is} 13 is         the console.log (head.data); 14} the else { 15         the console.log ( "empty list"); 16} 17} 

▉ Performance Analysis

1, to achieve reverse list

● time complexity: O (n). Need to traverse the entire list, time complexity is O (n).

● space complexity: O (1). No additional stack memory space, the space complexity is O (1).

2, stack implementation cycle

● time complexity: O (n). Need to traverse the entire list, time complexity is O (n).

● space complexity: O (n). Stack requires additional storage space, the space complexity is O (n).

3, recursive

● time complexity: O (n). Need to traverse the entire list, time complexity is O (n).

● space complexity: O (n). Stack requires additional storage space, the space complexity is O (n).

2.2 Summary

▉ study content

1, the basic operation of a single list.

2, the robustness of the code.

3, loops, recursion, stack flexibility.

▉ expansion thinking: loops and recursion

※ Conditions: If multiple compute the same problem, the use of loop or recursive manner.

※ recursive advantages: the code simple.

※ recursive disadvantages:

1, a stack overflow: function calls itself, the temporary variables that push operation, when the function is executed, the stack was empty, if the size of recursion is too large, has been implementing its own function inside the function call, the temporary variable has been pushed onto the stack The system stack or virtual machine stack memory is small, resulting in a stack overflow.

2, double counting: Recursive will be a lot of double counting, double counting has great influence on the performance, resulting in an exponential growth in consumption of time, but can be resolved by way hash table.

3, the high spatial complexity: recursive function calls every time to be involved in memory to open space, push, pop and other operations, i.e., time-consuming and space-consuming, resulting in a recursive cycle efficiency is not as efficient.

Extended:

1, recursion - Stack: Stack is recursive nature, the problem is usually solved with a stack suitable for recursive loop.

2, recursive - dynamic programming: dynamic programming problem solving analysis problems often recursive thinking. About recursive problem of double counting, we usually use the bottom-up solution ideas (dynamic programming) to solve the problem of double counting of recursion.

▉ Notes

1, related to circulatory problems to solve, you can think of can be solved using recursion.

2, solve performance problems we must bear in mind the disadvantages of using recursive recursive.

3, recursive problem to solve, can be solved by dynamic programming, making higher performance.

4, use this stack data structure, think about whether you can achieve it recursively.

In addition to this problem, there are a few questions about the list of classic examples, see in reading the original text, but also for each question were more detailed analysis.

Note: Due to the length of the article is too large, the rest of the analysis of several key topics in Github, click on the "read the original text," check the remaining topics analyzed in detail.

Phase Three: LeetCode strengthen the practice phase

If you have mastered the basic operation of the list, want to improve operating proficiency on the list, you can practice the LeetCode topic. Each question I have done a detailed analysis, such as: problem analysis, algorithm ideas, code implementation, test content and other relevant topics related to the list will be constantly updated ......

1, the annular chain I (☛ title analytical)

2, endless chain II (☛ title analytical)

3, K merge sort list (title ☛ analysis)

List summary

After a lot of questions about the list, the list of operations and re-set to make a summary of the list have an overall grasp and re-understanding.

1, the structure

Stored list of memory space is not continuous, all require the use of pointers to these fragmented memory space to connect, resulting in the need to operate through a pointer, which is why most of the list of reasons for pointer operations.

There are two lists in the structure special place is head of the list and end of the list, many of the operations to be head of the list and end of the list of special treatment, so we can (add a sentry at the list head) With Sentinel idea, so take the lead list you can simplify the solution to the problem.

2, the operation

Recursion: many of the operations are the list can be recursively solved, since each node in the list have the same structure, the problem can be solved together with the decomposition to solve sub-problems. Therefore, in the list of recursive programming skills are still very popular. Such as: the print head from the end of the list, merging two sorted linked list, like inverted list.

Double pointer: mostly linked list pointer operation performed, a linear table belonging to the list structure (structure of a line shape), a lot of problems can be solved using the double pointer, is also very common to. Such as: Find K penultimate node, intermediate node list request and the like.

3, performance

It is precisely because the list is not continuous storage space for CPU cache unfriendly, feel free to visit only traverse the list from scratch, time complexity is O (n), but the structure of the list there is a benefit that. Can dynamically allocate memory space, you do not need to apply in advance.

Pointer storage requires additional memory space is much greater than if the storage pointer data storage memory space and can be ignored.

Mapping knowledge, questions papers | linked list data structures and algorithms of the series

Guess you like

Origin www.cnblogs.com/xinzhihao/p/11010240.html