【面试题015】链表中倒数第k个结点
【面试题015】链表中倒数第k个结点
可以用两个指针,当第一个指针指向了第k个时候,第二个指针让他指向链表的第一个元素,然后这两个指针同时向后面移动,
当第一个指针移动到末尾的时候,第二个指针指向的就是倒数第K个结点;两个指针的间距保持为k-1;
当我们遍历列表的时候发现用一个指针是解决不了问题的,我们可以尝试用两个指针来解决问题,
一个指针走的比另外一个指针走得快一点,或者先让其中的一个指针走了若干步,然后再让第二个指针来走;
kth.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include <iostream>
#include <cstdio> #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; } } pBehind = pListHead; while(pAhead->m_pNext != NULL) { pAhead = pAhead->m_pNext; pBehind = pBehind->m_pNext; } return pBehind; } // 测试要找的结点在链表中间 int main() { printf("=====Test1 starts:=====\n"); 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); return 0; } |
运行结果:
=====Test1 starts:=====
expected result: 4.
The key in node is 4.
请按任意键继续. . .
List.h:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#ifndef _LIST_H_
#define _LIST_H_ 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); #endif //_LIST_H_ |
List.cpp:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
#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; } } if(pToBeDeleted != NULL) { delete pToBeDeleted; pToBeDeleted = NULL; } } |
Makefile:
1
2 3 4 5 6 7 8 9 10 11 12 |
.PHONY:clean
CPP=g++ CFLAGS=-Wall -g BIN=test OBJS=Kth.o List.o LIBS= $(BIN):$(OBJS) $(CPP) $(CFLAGS) $^ -o $@ $(LIBS) %.o:%.cpp $(CPP) $(CFLAGS) -c $< -o $@ clean: rm -f *.o $(BIN) |