Question: two one-way linked lists to find their first public node.
The linked list node is defined:
Struct listnode
{
Int m_nkey;
Listnode * m_pnext;
};
Analysis: This is a Microsoft interview question. Microsoft is very fond of linked list-related questions, so in Microsoft's interview questions, the probability of a linked list appearing is quite high.
If two one-way linked lists have public nodes, that is, the two linked lists start from a certain node and Their m_pnext points to the same node. But because it is a one-way linked list node, each node has only one m_pnext, so from the first public node, after all their nodes are overlapped, it is impossible to have a fork. Therefore, the topology of two linked lists with public nodes partially overlapped looks like a Y, rather than X.
Seeing this question, the first reaction is the brute force method: traverse each node in sequence on the first linked list. Each time a node is traversed, each node is sequentially traversed on the second linked list. If the nodes on the two linked lists are the same at this time, it means that the two linked lists overlap, and their public nodes are found. If the length of the first linked list is m and the length of the second linked list is N, it is obvious that the time complexity of this method is O (Mn ).
Next we try to find an algorithm with linear time complexity. Let's first simplify the problem: how can we determine whether two one-way linked lists have public nodes? As mentioned above, if two linked lists have a public node, all the nodes after the public node will overlap. Then, their last node must overlap. Therefore, we can determine whether two linked lists overlap each other by traversing the two linked lists to the last node. If the two end nodes are the same, they are overlapped. Otherwise, the two linked lists do not have public nodes.
In the above thinking, when we traverse two linked lists to the End Node sequentially, we cannot guarantee that the two linked lists will reach the end node at the same time. This is because the two linked lists do not necessarily have the same length. However, if one linked list has more than one node long than the other, we first traverse more than one node on the long linked list, and then synchronize the traversal, at this time, we can ensure that the last node is reached at the same time. Because the two linked lists take the test from the first public node to the End Node of the linked list, this part is overlapped. Therefore, they must also reach the first public node at the same time. Therefore, in traversal, the first same node is the first public node.
In this way, we first need to traverse the two linked lists to obtain their lengths and find the difference between the two lengths. After traversing the long linked list several times, you can traverse the two linked lists synchronously to find the same node, or until the end of the linked list. At this point, if the length of the first linked list is m and the length of the second linked list is N, the time complexity of this method is O (m + n ).
Based on this idea, we can easily write the following code:
///////////////////////////////////////////////////////////////////////// Find the first common node in the list with head pHead1 and// the list with head pHead2// Input: pHead1 - the head of the first list// pHead2 - the head of the second list// Return: the first common node in two list. If there is no common// nodes, return NULL///////////////////////////////////////////////////////////////////////ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2){ // Get the length of two lists unsigned int nLength1 = ListLength(pHead1); unsigned int nLength2 = ListLength(pHead2); int nLengthDif = nLength1 - nLength2; // Get the longer list ListNode *pListHeadLong = pHead1; ListNode *pListHeadShort = pHead2; if(nLength2 > nLength1) { pListHeadLong = pHead2; pListHeadShort = pHead1; nLengthDif = nLength2 - nLength1; } // Move on the longer list for(int i = 0; i < nLengthDif; ++ i) pListHeadLong = pListHeadLong->m_pNext; // Move on both lists while((pListHeadLong != NULL) && (pListHeadShort != NULL) && (pListHeadLong != pListHeadShort)) { pListHeadLong = pListHeadLong->m_pNext; pListHeadShort = pListHeadShort->m_pNext; } // Get the first common node in two lists ListNode *pFisrtCommonNode = NULL; if(pListHeadLong == pListHeadShort) pFisrtCommonNode = pListHeadLong; return pFisrtCommonNode;} ///////////////////////////////////////////////////////////////////////// Get the length of list with head pHead// Input: pHead - the head of list// Return: the length of list///////////////////////////////////////////////////////////////////////unsigned int ListLength(ListNode* pHead){ unsigned int nLength = 0; ListNode* pNode = pHead; while(pNode != NULL) { ++ nLength; pNode = pNode->m_pNext; } return nLength;}
Source: http://zhedahht.blog.163.com /.