Http://zhedahht.blog.163.com/blog/static/2541117420072114478828/

Question: enter a one-way linked list and output the penultimate in this linked list.KNodes. The penultimate of the linked list0Nodes are the tail pointer of the linked list. The linked list node is defined as follows:

struct listnode

{< br> int m_nkey;

listnode * m_pnext;

};

analysis: to get the last K node, it is natural to go to the end of the linked list first, back to the K step from the end. However, the input is a one-way linked list. Only the pointer from the past to the next is not the pointer from the back to the next. Therefore, we need to open up our ideas.

since we cannot traverse the linked list from the End Node, we should move our thinking back to the header node. Assume that the entire linked list has n nodes, so the last K node is the beginning of the node n-k-1 nodes (counted from 0 ). If we can obtain the number of nodes in the linked list n , then we just need to start from the node back to the n-k-1 step on it. How do I get the number of knots n ? This is not difficult. You only need to start the traversal chain table from the beginning. Each time you go through a node, you can add one to the counter.

The time complexity of this approach isO (N). Obtain the number of nodes in the linked list for the first time.NFor the second time, obtainN-k-1Node (the penultimate)KNodes.

If the number of knots in the linked list is small, this is a good method. However, if the number of nodes in the input linked list is large, it is possible that the entire linked list cannot be read from the hard disk into the physical memory at one time, traversing twice means that a node needs to be read twice from the hard disk to the physical memory. It is time-consuming to read data from the hard disk to the memory. Can we reduce the number of linked list traversal times1? If yes, it will be effectively improvedCodeExecution time efficiency.

If we maintain two pointers during the traversal, the first pointer traverses from the head pointer of the linked list.K-1Before the step, the second pointer remains unchanged.K-1The second pointer also starts to traverse from the head pointer of the linked list. Because the distance between the two pointers remainsK-1When the first (walking in front) pointer reaches the end of the linked list, the second pointer (walking behind) pointer is exactly the penultimateKNodes.

In this way, you only need to traverse a table once. For a long linked list, you only need to import each node from the hard disk to the memory once. Therefore, the time efficiency of this method is higher than that of the previous method.

Reference code for IDEA 1:

//////////////////////////////////////// /// // Find the kth node from the tail of a list // input: plisthead-the head of list // K-the distance to the tail // output: the Kth node from the tail of a list /////////////////////////////// //////////////////////////////////////// listnode * findkthtotail_solution1 (listnode * plisthead, unsigned int K) {If (plisthead = NULL) retur N null; // count the nodes number in the list listnode * pcur = plisthead; unsigned int nnum = 0; while (pcur-> m_pnext! = NULL) {pcur = pcur-> m_pnext; nnum ++;} // if the number of nodes in the list is less than K // do nothing if (nnum <K) return NULL; // The Kth node from the tail of a list // is the (n-k) Th node from the head pcur = plisthead; For (unsigned int I = 0; I <nnum-K; ++ I) pcur = pcur-> m_pnext; return pcur ;}

Reference code for idea 2:

//////////////////////////////////////// /// // Find the kth node from the tail of a list // input: plisthead-the head of list // K-the distance to the tail // output: the Kth node from the tail of a list /////////////////////////////// //////////////////////////////////////// listnode * findkthtotail_solution2 (listnode * plisthead, unsigned int K) {If (plisthead = NULL) retur N null; listnode * pahead = plisthead; listnode * pbehind = NULL; For (unsigned int I = 0; I <K; ++ I) {If (pahead-> m_pnext! = NULL) pahead = pahead-> m_pnext; else {// if the number of nodes in the list is less than K, // do nothing return NULL;} pbehind = plisthead; // The distance between pahead and pbehind is K // when pahead arrives at the tail, P // behind is at the kth node from the tail while (pahead-> m_pnext! = NULL) {pahead = pahead-> m_pnext; pbehind = pbehind-> m_pnext;} return pbehind ;}

discussion: the code for this question has a lot of pointer operations. In software development, incorrect pointer operations are the root cause of most problems. Therefore, every company wants Program Members to have good habits in operating pointers, such as determining whether a pointer is null before using pointers. These are the details of programming, but if these details are not well grasped, it is very likely to lose hands with your favorite company.

In addition, the Code corresponding to these two ideas contains loops. A common problem with code containing loops is the judgment of the loop end condition. Should I use less than or equal? YesKStill useK-1? Because the question is from0Start counting, and our habit of thinking is from1Start counting, so you must first think about these boundary conditions before writing code, and then use the Boundary Value and boundary value minus after writing the code.1, Boundary value plus1All run once (write code on paper and you can only run it in your mind ).

Extension: similar to this question, you can also enter a one-way linked list. If the number of knots in the linked list is an odd number, the intermediate node is output. If the number of knots in the linked list is an even number, one before the two nodes is output. If you are interested, analyze and write your own code.