转载并参考July的博客http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html,万分感谢!
题目:
输入一个单向链表,输出该链表中倒数第k个结点,链表的倒数第0个结点为链表的尾指针。
分析:
因为是单向链表,不能从尾部向头部遍历,所以要找到一种合适的方法遍历到倒数第K个节点。
解一:
假设整个链表有n个结点,那么倒数第k个结点是从头结点开始的第n-k-1个结点(从0开始计数)。如果我们能够得到链表中结点的个数n,那我们只要从头结点开始往后走n-k-1步就可以了。如何得到结点数n?这个不难,只需要从头开始遍历链表,每经过一个结点,计数器加一就行了。这种思路的时间复杂度是O(n),但需要遍历链表两次。第一次得到链表中结点个数n,第二次得到从头结点开始的第n-k-1个结点即倒数第k个结点。
/*Title: 13.求单向链表倒数第k个节点:解一 Author: gocode Date: 2012-10-15*/ #include <iostream> using namespace std; struct ListNode { int m_nKey; ListNode* m_pNext; }; ListNode* Head; ListNode* pCur; void AddToList(ListNode* &pCur, unsigned int key) { if(pCur == NULL) { ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->m_nKey = key; newNode->m_pNext = NULL; pCur = newNode; Head = newNode; } else { ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->m_nKey = key; newNode->m_pNext = NULL; pCur->m_pNext = newNode; pCur = newNode; } } ListNode* FindKthToTail_Solution1(ListNode* pListHead, unsigned int k) { if(pListHead == NULL) return NULL; // 计算链表里节点个数 ListNode *pCur = pListHead; unsigned int nNum = 0; while(pCur != NULL) { pCur = pCur->m_pNext; nNum ++; } // 如果链表节点数小于k,则退出 if(nNum < k) return NULL; // 倒数第k个节点也是整数第n-k个节点 // 找到它 pCur = pListHead; for(unsigned int i = 0; i < nNum - k; ++ i) pCur = pCur->m_pNext; return pCur; } void DisplayList(ListNode* pHead) { ListNode* p = pHead; if(p == NULL) cout<<"The LinkedList is empty."<<endl; else { while(p != NULL) { cout<<p->m_nKey<<" "; p = p->m_pNext; } } cout<<endl; } void main() { Head = pCur = NULL; AddToList(pCur, 1); AddToList(pCur, 2); AddToList(pCur, 3); AddToList(pCur, 4); AddToList(pCur, 5); AddToList(pCur, 6); AddToList(pCur, 7); DisplayList(Head); cout<<"13.求单向链表倒数第k个节点:解一"<<endl; cout<<"The Kth from tail is: "<<FindKthToTail_Solution1(Head, 3)->m_nKey<<endl; system("pause"); }
解二:
设置p1和p2两个指针,开始时均指向头指针head,然后p2向后移动k个节点,接着同时移动p1和p2节点,当p2指向尾部NULL时,此时p1指向的就是倒数第k个节点。
/*Title: 13.求单向链表倒数第k个节点:解二 Author: gocode Date: 2012-10-15*/ #include <iostream> using namespace std; struct ListNode { int m_nKey; ListNode* m_pNext; }; ListNode* Head; ListNode* pCur; void AddToList(ListNode* &pCur, unsigned int key) { if(pCur == NULL) { ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->m_nKey = key; newNode->m_pNext = NULL; pCur = newNode; Head = newNode; } else { ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->m_nKey = key; newNode->m_pNext = NULL; pCur->m_pNext = newNode; pCur = newNode; } } ListNode* FindKthToTail_Solution2(ListNode* pListHead, unsigned int k) { if(pListHead == NULL) return NULL; ListNode *p1, *p2 = pListHead; unsigned int nNum = 1; while(p2 != NULL) { p2 = p2->m_pNext; nNum ++; if(nNum == k) // 结束条件 break; } // if the number of nodes in the list is less than k // do nothing if(nNum < k) return NULL; // 现在p1和p2之间的距离保持为k个节点 // 同时移动它们,直到p2指向NULL p1 = pListHead; while(p2->m_pNext != NULL) { p1 = p1->m_pNext; p2 = p2->m_pNext; } return p1; } void DisplayList(ListNode* pHead) { ListNode* p = pHead; if(p == NULL) cout<<"The LinkedList is empty."<<endl; else { while(p != NULL) { cout<<p->m_nKey<<" "; p = p->m_pNext; } } cout<<endl; } void main() { Head = pCur = NULL; AddToList(pCur, 1); AddToList(pCur, 2); AddToList(pCur, 3); AddToList(pCur, 4); AddToList(pCur, 5); AddToList(pCur, 6); AddToList(pCur, 7); DisplayList(Head); cout<<"13.求单向链表倒数第k个节点:解二"<<endl; cout<<"The Kth from tail is: "<<FindKthToTail_Solution2(Head, 3)->m_nKey<<endl; system("pause"); }