// 面试题23:链表中环的入口结点
// 题目:一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中,
// 环的入口结点是结点3。
ListNode* FindFirstNode(ListNode* HeadNode) { if(!HeadNode) return nullptr; ListNode* FastNode = HeadNode; ListNode* SlowNode = HeadNode; while(FastNode&(FastNode->NextPoint)) { SlowNode = SlowNode->NextPoint; FastNode = SlowNode->NextPoint; if(FastNode == SlowNode) { SlowNode = HeadNode; while(FastNode != SlowNode) { FastNode = FastNode->NextPoint; SlowNode = SlowNode->NextPoint; } return SlowNode; } } return nullptr; }
//找到链表中环形链表的入口点 ListNode* FindTheFirstNode(ListNode* Node) { if(Node ==nullptr) return nullptr; ListNode* Fastp = Node; ListNode Slowp = Node; while((Fastp!= Slowp)&(Fastp!=nullptr)) { Fastp = Fastp->NextPoint->NextPoint; Slowp = Slowp->NextPoint; } Slowp =Node; while(SLowp != Fastp) { Slowp = Slowp->NextPoint; Fastp = Fastp->NextPoint; } return slowp; }
// 面试题22:链表中倒数第k个结点
// 题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,
// 本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,
// 从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是
// 值为4的结点。
#include <cstdio> #include "..UtilitiesList.h" ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { if(pListHead == nullptr || k == 0) return nullptr; ListNode *pAhead = pListHead; ListNode *pBehind = nullptr; for(unsigned int i = 0; i < k - 1; ++ i) { if(pAhead->m_pNext != nullptr) pAhead = pAhead->m_pNext; else { return nullptr; } } pBehind = pListHead; while(pAhead->m_pNext != nullptr) { pAhead = pAhead->m_pNext; pBehind = pBehind->m_pNext; } return pBehind; } // ====================测试代码==================== // 测试要找的结点在链表中间 void Test1() { printf("=====Test1 starts:===== "); ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode5); printf("expected result: 4. "); ListNode* pNode = FindKthToTail(pNode1, 2); PrintListNode(pNode); DestroyList(pNode1); } // 测试要找的结点是链表的尾结点 void Test2() { printf("=====Test2 starts:===== "); ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode5); printf("expected result: 5. "); ListNode* pNode = FindKthToTail(pNode1, 1); PrintListNode(pNode); DestroyList(pNode1); } // 测试要找的结点是链表的头结点 void Test3() { printf("=====Test3 starts:===== "); ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode5); printf("expected result: 1. "); ListNode* pNode = FindKthToTail(pNode1, 5); PrintListNode(pNode); DestroyList(pNode1); } // 测试空链表 void Test4() { printf("=====Test4 starts:===== "); printf("expected result: nullptr. "); ListNode* pNode = FindKthToTail(nullptr, 100); PrintListNode(pNode); } // 测试输入的第二个参数大于链表的结点总数 void Test5() { printf("=====Test5 starts:===== "); ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode5); printf("expected result: nullptr. "); ListNode* pNode = FindKthToTail(pNode1, 6); PrintListNode(pNode); DestroyList(pNode1); } // 测试输入的第二个参数为0 void Test6() { printf("=====Test6 starts:===== "); ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode5); printf("expected result: nullptr. "); ListNode* pNode = FindKthToTail(pNode1, 0); PrintListNode(pNode); DestroyList(pNode1); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); return 0; }
// 面试题52:两个链表的第一个公共结点
// 题目:输入两个链表,找出它们的第一个公共结点。
#include <cstdio> #include "..UtilitiesList.h" unsigned int GetListLength(ListNode* pHead); ListNode* FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2) { // 得到两个链表的长度 unsigned int nLength1 = GetListLength(pHead1); unsigned int nLength2 = GetListLength(pHead2); int nLengthDif = nLength1 - nLength2; ListNode* pListHeadLong = pHead1; ListNode* pListHeadShort = pHead2; if(nLength2 > nLength1) { pListHeadLong = pHead2; pListHeadShort = pHead1; nLengthDif = nLength2 - nLength1; } // 先在长链表上走几步,再同时在两个链表上遍历 for(int i = 0; i < nLengthDif; ++i) pListHeadLong = pListHeadLong->m_pNext; while((pListHeadLong != nullptr) && (pListHeadShort != nullptr) && (pListHeadLong != pListHeadShort)) { pListHeadLong = pListHeadLong->m_pNext; pListHeadShort = pListHeadShort->m_pNext; } // 得到第一个公共结点 ListNode* pFisrtCommonNode = pListHeadLong; return pFisrtCommonNode; } unsigned int GetListLength(ListNode* pHead) { unsigned int nLength = 0; ListNode* pNode = pHead; while(pNode != nullptr) { ++nLength; pNode = pNode->m_pNext; } return nLength; } // ====================测试代码==================== void DestroyNode(ListNode* pNode); void Test(char* testName, ListNode* pHead1, ListNode* pHead2, ListNode* pExpected) { if(testName != nullptr) printf("%s begins: ", testName); ListNode* pResult = FindFirstCommonNode(pHead1, pHead2); if(pResult == pExpected) printf("Passed. "); else printf("Failed. "); } // 第一个公共结点在链表中间 // 1 - 2 - 3 // 6 - 7 // 4 - 5 / void Test1() { ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ListNode* pNode6 = CreateListNode(6); ListNode* pNode7 = CreateListNode(7); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode6); ConnectListNodes(pNode4, pNode5); ConnectListNodes(pNode5, pNode6); ConnectListNodes(pNode6, pNode7); Test("Test1", pNode1, pNode4, pNode6); DestroyNode(pNode1); DestroyNode(pNode2); DestroyNode(pNode3); DestroyNode(pNode4); DestroyNode(pNode5); DestroyNode(pNode6); DestroyNode(pNode7); } // 没有公共结点 // 1 - 2 - 3 - 4 // // 5 - 6 - 7 void Test2() { ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ListNode* pNode6 = CreateListNode(6); ListNode* pNode7 = CreateListNode(7); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode5, pNode6); ConnectListNodes(pNode6, pNode7); Test("Test2", pNode1, pNode5, nullptr); DestroyList(pNode1); DestroyList(pNode5); } // 公共结点是最后一个结点 // 1 - 2 - 3 - 4 // 7 // 5 - 6 / void Test3() { ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ListNode* pNode6 = CreateListNode(6); ListNode* pNode7 = CreateListNode(7); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode7); ConnectListNodes(pNode5, pNode6); ConnectListNodes(pNode6, pNode7); Test("Test3", pNode1, pNode5, pNode7); DestroyNode(pNode1); DestroyNode(pNode2); DestroyNode(pNode3); DestroyNode(pNode4); DestroyNode(pNode5); DestroyNode(pNode6); DestroyNode(pNode7); } // 公共结点是第一个结点 // 1 - 2 - 3 - 4 - 5 // 两个链表完全重合 void Test4() { ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode5); Test("Test4", pNode1, pNode1, pNode1); DestroyList(pNode1); } // 输入的两个链表有一个空链表 void Test5() { ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode5); Test("Test5", nullptr, pNode1, nullptr); DestroyList(pNode1); } // 输入的两个链表有一个空链表 void Test6() { Test("Test6", nullptr, nullptr, nullptr); } void DestroyNode(ListNode* pNode) { delete pNode; pNode = nullptr; } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); return 0; }
// 面试题51:数组中的逆序对
// 题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组
// 成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
#include <cstdio> int InversePairsCore(int* data, int* copy, int start, int end); int InversePairs(int* data, int length) { if(data == nullptr || length < 0) return 0; int* copy = new int[length]; for(int i = 0; i < length; ++i) copy[i] = data[i]; int count = InversePairsCore(data, copy, 0, length - 1); delete[] copy; return count; } int InversePairsCore(int* data, int* copy, int start, int end) { if(start == end) { copy[start] = data[start]; return 0; } int length = (end - start) / 2; int left = InversePairsCore(copy, data, start, start + length); int right = InversePairsCore(copy, data, start + length + 1, end); // i初始化为前半段最后一个数字的下标 int i = start + length; // j初始化为后半段最后一个数字的下标 int j = end; int indexCopy = end; int count = 0; while(i >= start && j >= start + length + 1) { if(data[i] > data[j]) { copy[indexCopy--] = data[i--]; count += j - start - length; } else { copy[indexCopy--] = data[j--]; } } for(; i >= start; --i) copy[indexCopy--] = data[i]; for(; j >= start + length + 1; --j) copy[indexCopy--] = data[j]; return left + right + count; } // ====================测试代码==================== void Test(char* testName, int* data, int length, int expected) { if(testName != nullptr) printf("%s begins: ", testName); if(InversePairs(data, length) == expected) printf("Passed. "); else printf("Failed. "); } void Test1() { int data[] = { 1, 2, 3, 4, 7, 6, 5 }; int expected = 3; Test("Test1", data, sizeof(data) / sizeof(int), expected); } // 递减排序数组 void Test2() { int data[] = { 6, 5, 4, 3, 2, 1 }; int expected = 15; Test("Test2", data, sizeof(data) / sizeof(int), expected); } // 递增排序数组 void Test3() { int data[] = { 1, 2, 3, 4, 5, 6 }; int expected = 0; Test("Test3", data, sizeof(data) / sizeof(int), expected); } // 数组中只有一个数字 void Test4() { int data[] = { 1 }; int expected = 0; Test("Test4", data, sizeof(data) / sizeof(int), expected); } // 数组中只有两个数字,递增排序 void Test5() { int data[] = { 1, 2 }; int expected = 0; Test("Test5", data, sizeof(data) / sizeof(int), expected); } // 数组中只有两个数字,递减排序 void Test6() { int data[] = { 2, 1 }; int expected = 1; Test("Test6", data, sizeof(data) / sizeof(int), expected); } // 数组中有相等的数字 void Test7() { int data[] = { 1, 2, 1, 2, 1 }; int expected = 3; Test("Test7", data, sizeof(data) / sizeof(int), expected); } void Test8() { int expected = 0; Test("Test8", nullptr, 0, expected); } int main(int argc, char* argv[]) { Test1(); Test2(); Test3(); Test4(); Test5(); Test6(); Test7(); Test8(); return 0; }