两个链表
参考:http://zhedahht.blog.163.com
- 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是按照增序排列的。
- 输入两个单链表(无环),找出他们的第一个公共节点。
- 判断两个单链表(可能有环)是否相交。
1、思路:
类似与归并排序,但是这里只需要修改指针指向,不需要另辟空间,通过递归的方式,从后往前拼接链表。
MergeList
1 ListNode* Merge(ListNode* pHead1, ListNode* pHead2) 2 { 3 if(pHead1 == NULL) 4 return pHead2; 5 else if(pHead2 == NULL) 6 return pHead1; 7 8 ListNode* pMergedHead = NULL; 9 10 if(pHead1->m_nValue < pHead2->m_nValue) 11 { 12 pMergedHead = pHead1; 13 pMergedHead->m_pNext = Merge(pHead1->m_pNext, pHead2); 14 } 15 else 16 { 17 pMergedHead = pHead2; 18 pMergedHead->m_pNext = Merge(pHead1, pHead2->m_pNext); 19 } 20 21 return pMergedHead; 22 }
2、思路:
如果有公共节点,则最后一个节点肯定是,再倒序回去就能找到第一个公共节点。采用“栈”,这样时间复杂度是O(m+n),空间复杂度是O(m+n)。如果预先计算两个链表的长度,记录长度差,然后先让长链表的指针率先前进长度差步,再两个指针同时前进就能找到第一个公共点,时间复杂度没有变,空间复杂度是O(1)。
FindFirstCommonNode
1 unsigned int GetListLength(ListNode* pHead); 2 3 ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) 4 { 5 // 得到两个链表的长度 6 unsigned int nLength1 = GetListLength(pHead1); 7 unsigned int nLength2 = GetListLength(pHead2); 8 int nLengthDif = nLength1 - nLength2; 9 10 ListNode* pListHeadLong = pHead1; 11 ListNode* pListHeadShort = pHead2; 12 if(nLength2 > nLength1) 13 { 14 pListHeadLong = pHead2; 15 pListHeadShort = pHead1; 16 nLengthDif = nLength2 - nLength1; 17 } 18 19 // 先在长链表上走几步,再同时在两个链表上遍历 20 for(int i = 0; i < nLengthDif; ++ i) 21 pListHeadLong = pListHeadLong->m_pNext; 22 23 while((pListHeadLong != NULL) && 24 (pListHeadShort != NULL) && 25 (pListHeadLong != pListHeadShort)) 26 { 27 pListHeadLong = pListHeadLong->m_pNext; 28 pListHeadShort = pListHeadShort->m_pNext; 29 } 30 31 // 得到第一个公共结点 32 ListNode* pFisrtCommonNode = pListHeadLong; 33 34 return pFisrtCommonNode; 35 } 36 37 unsigned int GetListLength(ListNode* pHead) 38 { 39 unsigned int nLength = 0; 40 ListNode* pNode = pHead; 41 while(pNode != NULL) 42 { 43 ++ nLength; 44 pNode = pNode->m_pNext; 45 } 46 47 return nLength; 48 }
3、思路:
先判断带不带环,如果其中一个带环,另一个不带环,则肯定不想交;如果都不带环,就判断尾节点是否相等;如果都带环,则判断一链表上俩指针相遇的那个节点,在不在另一条链表上。