剑指Offer:面试题15 链表中倒数第k个结点
2014-09-08 19:39
405 查看
/* 链表中倒数第k个节点: 输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是 倒数第一个节点。例如一个链表有6个节点,从头节点开始它们的值依次是1,2,3,4,5,6。这个链表的倒数第三个 节点是值为4的结点。 输入: 输入可能包含多个测试样例,输入以EOF结束。 对于每个测试案例,输入的第一行为两个整数n和k(0<=n<=1000, 0<=k<=1000):n代表将要输入的链表元素的个数,k代表要查询倒数第几个的元素。 输入的第二行包括n个数t(1<=t<=1000000):代表链表中的元素。 输出: 对应每个测试案例, 若有结果,输出相应的查找结果。否则,输出NULL。 样例输入: 5 2 1 2 3 4 5 1 0 5 样例输出: 4 NULL 要考虑k的取值: k = 0,返回NULL 加入k > n,此时应该也返回NULL 0< k <= n,返回倒数第k个节点 */ /* 关键: 1 若开始p1 = p2 = 头节点指针(头节点算第一个节点),那么p1走k-1(因为第一步已经走了)步之后,大家一起走就可以(推荐这种) 若p1 = p2 = NULL,那么p1走k步后,两者一起走 */ #include <stdio.h> const int INF = 1000000000; const int MAXSIZE = 1001; typedef struct Node { int _iVal; struct Node* _next; }Node; void buildList_headInsert(Node** pHead,int n,int* pArr) { if(pHead == NULL || n < 0 || pArr == NULL) { return; } //头插法的玄机:每次使新插入的节点指向刚刚的头结点,然后使自己成为头节点 //Node* pRearNode = *pHead; //pRearNode->_next = Node* pNode,*pFrontNode,*pRearNode;//因为刚开始的头结点最终会在头插法下变成最后的结点 for(int i = 0 ; i < n ;i++) { pNode = new Node(); pNode->_iVal = pArr[i]; if(i) { pNode->_next = pFrontNode;//指向刚才的上一个节点 pFrontNode = pNode; } else { pNode->_next = NULL;//设置指向为空 pFrontNode = pRearNode = pNode; } } pRearNode->_next = NULL;//设置尾节点的指向为空 *pHead = pFrontNode; } void buildList(Node** pHead,int n,int* pArr)//采用尾插法 { if(pHead == NULL || n < 0 || pArr == NULL) { return; } Node* pCurNode; for(int i = 0 ; i < n ; i++) { if(i) { Node* pNode = new Node(); pNode->_iVal = pArr[i]; pNode->_next = NULL; pCurNode->_next = pNode; pCurNode = pNode; } else//建立头结点 { (*pHead)->_iVal = pArr[i]; (*pHead)->_next = NULL; pCurNode = (*pHead); } } } void freeList(Node** pHead)//删除链表 { Node* pNode; while((*pHead) != NULL) { pNode = *pHead; *pHead = (*pHead)->_next; delete pNode; pNode = NULL; } } //倒数第k个节点,1,2,3,4,5,6,k = 3,可以另p1 = 1,p2 = 1,p1走到3处(走了k-1次),然后p2 与 p1 一起走剩下的n-k+1次,则p2一共走: int reciprocalKNode(int n,int k,int* pArr)// { if(k <= 0 || k > n)//鲁棒性 { return INF; } Node* head = new Node(); Node** pHead = &head;//这样做的原因是:好让头指针能够修改,若直接传递Node*作为头节点,则修改后会作为局部变量最后消失 buildList_headInsert(pHead,n,pArr);//建立链表 Node* p1,*p2; p1 = p2 = *pHead; //p1先走k-1步之后,p1与p2再一起走 int iCnt = 0; while(p1->_next != NULL) { if(iCnt < k - 1)//k-1 - 1 + 1 = 等于走了k-1步 { iCnt++; } else//如果iCnt 已经大于k-1,表名p1已经走完 { p2 = p2->_next; } p1 = p1 ->_next; } int iRes = p2->_iVal; freeList(pHead); return iRes; } void process() { int n,k; while(EOF != scanf("%d %d",&n,&k)) { int iArr[MAXSIZE]; for(int i = 0 ; i < n ; i++) { scanf("%d",&iArr[i]); } int iRes = reciprocalKNode(n,k,iArr); if(iRes != INF) { printf("%d\n",iRes); } else { printf("NULL\n"); } } } int main(int argc,char* argv[]) { process(); getchar(); return 0; }
相关文章推荐
- 剑指offer代码解析——面试题15求链表中倒数第K个结点
- 【剑指offer】面试题15:链表中倒数第k个结点
- 【剑指Offer学习】【面试题15 :链表中倒数第k个结点】
- 【剑指Offer】面试题15:链表中倒数第K个结点
- 【剑指offer】面试题15:链表中倒数第k个结点
- 剑指Offer面试题15(Java版):链表中倒数第K个结点
- 剑指Offer学习之面试题15 :链表中倒数第k个结点
- 剑指offer--面试题15:链表中倒数第K个结点--Java实现
- 剑指Offer:面试题15——链表中倒数第k个结点(java实现)
- 剑指offer面试题15——链表中倒数第k个结点
- 【剑指offer】3.4代码的鲁棒性——面试题15:链表中倒数第k个结点
- 剑指offer-面试题15-链表中倒数第k个结点
- 【剑指offer 面试题15】链表中倒数第K个结点
- 剑指offer 面试题15: 链表中倒数第k个结点 题解
- 剑指offer-面试题15.链表中倒数第k个结点
- 剑指offer面试题15 链表中倒数第K个结点
- 剑指offer--面试题15:链表中倒数第k个结点
- 剑指Offer之面试题15:链表中倒数第K个结点
- 剑指offer-面试题15.链表中倒数第k个结点
- 【剑指offer】面试题15:链表中倒数第k个结点