面試題15:查詢連結串列中倒數第k個結點
阿新 • • 發佈:2019-01-04
1.題目:給定一個單鏈表,編寫函式,輸入一個連結串列,輸出連結串列中倒數第k個結點,其中倒數是從1開始計數,例如連結串列中的結點是1,2,3,4,5,6. 要查詢倒數第3個結點,會輸出4.
分析:比較傳統的做法就是,既然要查詢倒數k個結點,可以先編譯一遍連結串列,看連結串列中有多少個結點n,然後按順序查詢第n-k+1個結點就是要找的結點。但是這種方法需要遍歷連結串列2遍,並不是很高效。一種更高效的方法是:用兩個指標,一個指標先走k-1步,然後第二個指標也開始跟著一起走。當第一個指標到連結串列尾部的時候,第二個指標指向的就是連結串列中的導數第k個結點。
圖示:
但是在真正解決問題的時候,還要考慮到程式碼的魯棒性,例如連結串列是否為空,連結串列結點個數是否小於k,k是否為0等情況。
原始碼:
/*查詢連結串列中倒數第k個節點*/ #include<iostream> using namespace std; struct ListNode { int m_nValue; ListNode* m_pNext; }; //建立一個節點 ListNode* CreateListNode(int value) { ListNode* pNode = new ListNode(); pNode->m_nValue = value; pNode->m_pNext = NULL; return pNode; } //列印整個連結串列 void PrintList(ListNode* pHead) { printf("PrintList starts.\n"); ListNode* pNode = pHead; while (pNode != NULL) { printf("%d\t", pNode->m_nValue); pNode = pNode->m_pNext; } printf("\nPrintList ends.\n"); } //列印結點的值 void PrintListNode(ListNode* pNode) { if (pNode == NULL) { printf("The node is NULL\n"); } else { printf("The key in node is %d.\n", pNode->m_nValue); } } //將兩個結點連線起來 void ConnectListNodes(ListNode* pCurrent, ListNode* pNext) { if (pCurrent == NULL) { printf("Error to connect two nodes.\n"); exit(1); } pCurrent->m_pNext = pNext; } //銷燬連結串列 void DestroyList(ListNode* pHead) { ListNode* pNode = pHead; while (pNode != NULL) { pHead = pHead->m_pNext; delete pNode; pNode = pHead; } } //查詢倒數第k個節點 ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { if (pListHead == NULL || k == 0)//連結串列為空或者k值為0的情況 return NULL; ListNode *pAhead = pListHead; ListNode *pBehind = NULL; for (unsigned int i = 0; i < k - 1; ++i) { if (pAhead->m_pNext != NULL) pAhead = pAhead->m_pNext; else { return NULL;//連結串列中的結點的個數少於k的情況 } } pBehind = pListHead; while (pAhead->m_pNext != NULL) { pAhead = pAhead->m_pNext; pBehind = pBehind->m_pNext; } return pBehind; } int main() { //建立結點 ListNode* pNode1 = CreateListNode(1); ListNode* pNode2 = CreateListNode(2); ListNode* pNode3 = CreateListNode(3); ListNode* pNode4 = CreateListNode(4); ListNode* pNode5 = CreateListNode(5); ListNode* pNode6 = CreateListNode(6); //連成連結串列 ConnectListNodes(pNode1, pNode2); ConnectListNodes(pNode2, pNode3); ConnectListNodes(pNode3, pNode4); ConnectListNodes(pNode4, pNode5); ConnectListNodes(pNode5, pNode6); //列印連結串列 PrintList(pNode1); int chooseNo = 3; ListNode* result = FindKthToTail(pNode1, chooseNo); printf("倒數第%d個結點的資訊為:\n", chooseNo); PrintListNode(result);//輸入結果為4 DestroyList(pNode1); system("PAUSE"); return 0; }
結果