1. 程式人生 > >面試題15:查詢連結串列中倒數第k個結點

面試題15:查詢連結串列中倒數第k個結點

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;
}

結果