面试题15:链表中倒数第k个结点
题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第一个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。
预备知识:
链表结点的定义如下:
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
};思路:定义两个指针,第一个指针从链表的头指针开始遍历向前走k-1,第二个指针保存不动;从第k步开始,第二个指针也开始从链表的头指针开始遍历。因为两个指针的距离保存在k-1,因此当第一个指针达到链表的尾部时,第二个指针正好是倒数第k个结点。
算法实现:
/*******链表结点定义****/
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
};
/***************链表操作****************/
//创建链表结点
ListNode* CreateListNode(int value);
//链接链表结点
void ConnectListNodes(ListNode* pCurrent, ListNode* pNext);
//打印链表结点
void PrintListNode(ListNode* pNode);
//遍历链表的所有结点
void PrintList(ListNode* pHead);
//销毁链表
void DestroyList(ListNode* pHead);
//在链表尾部添加结点
void AddToTail(ListNode** pHead, int value);
//移除结点
void RemoveNode(ListNode** pHead, int value);#include "stdafx.h"
#include "List.h"
#include <stdio.h>
#include <stdlib.h>
//创建链表结点
ListNode* CreateListNode(int value)
{
ListNode* pNode = new ListNode(); //头指针
pNode->m_nValue = value;
pNode->m_pNext = NULL;
return pNode;
}
//链接链表结点
void ConnectListNodes(ListNode* pCurrent, ListNode* pNext)
{
if(pCurrent == NULL)
{
printf("Error to connect two nodes.\n");
exit(1);
}
pCurrent->m_pNext = pNext;
}
//打印链表结点
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 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 DestroyList(ListNode* pHead)
{
ListNode* pNode = pHead;
while(pNode !=NULL)
{
pHead = pHead->m_pNext;
delete pNode;
pNode = pHead;
}
}
//在链表尾部添加结点
void AddToTail(ListNode** pHead, int value)
{
ListNode* pNew = new ListNode();
pNew->m_nValue = value;
pNew->m_pNext = NULL;
if(*pHead == NULL)
{
*pHead = pNew;
}
else
{
ListNode* pNode = *pHead;
while(pNode->m_pNext != NULL)
pNode = pNode->m_pNext;
pNode->m_pNext = pNew;
}
}
//移除结点
void RemoveNode(ListNode** pHead, int value)
{
if(pHead == NULL || *pHead == NULL)
return;
ListNode* pToBeDeleted = NULL;
if((*pHead)->m_nValue == value)
{
pToBeDeleted = *pHead;
*pHead = (*pHead)->m_pNext;
}
else
{
ListNode* pNode = *pHead;
while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value)
pNode = pNode->m_pNext;
if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value)
{
pToBeDeleted = pNode->m_pNext;
pNode->m_pNext = pNode->m_pNext->m_pNext;
}
}
}main.cpp
// 面试题15.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "..\List.h"
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
if(pListHead == NULL || 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;
}
// ************测试代码******
void Test1()
{
printf("+++++++++++++\n");
//创建5个结点
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.\n");
ListNode* pNode = FindKthToTail(pNode1,2);
PrintListNode(pNode);
DestroyList(pNode1);
}
int _tmain(int argc, _TCHAR* argv[])
{
Test1();
return 0;
}
注意事项:
1. 输入的链表头指针可能为NULL
2. 输入的k可能为0
3 输入的链表结点个数小于k

879

被折叠的 条评论
为什么被折叠?



