剑指Offer——面试题22:链表中倒数第k个结点

面试题22:链表中倒数第k个结点
题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。
在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
struct ListNode{
	int value;
	ListNode* next;
};
/**
 * 方法一:遍历链表两次, 第一次统计出链表结点的个数, 第二次就能找到倒数第k个结点
 *    缺点:需要遍历链表两次 
 **/
ListNode* FindKthToTail1(ListNode* pListHead, unsigned int k){
	if(pListHead==NULL || k==0){
		return NULL;
	}
	ListNode* pNode=pListHead;
	int lengthOfList=0;
	while(pNode){
		lengthOfList++;
		pNode=pNode->next;
	}
	if(lengthOfList<k) return NULL;
	pNode=pListHead;
	int cnt=0;
	while(cnt!=lengthOfList-k+1){
		cnt++;
		pNode=pNode->next;
	}
	return pNode;
}
/**
 * 方法二:利用两个指针, 第一个指针从链表的头指针开始遍历向前走 k-1 步,第二个指针保持不动,
 *      再两个指针同时移动, 直到第一个指针到链表末尾, 第二个指针指向的元素即为所求元素 
 **/
ListNode* FindKthToTail2(ListNode* pListHead, unsigned int k){
	if(pListHead==NULL || k==0){
		return NULL;
	}
	ListNode* p1=pListHead;
	ListNode* p2=NULL;
	for(unsigned int i=0;i<k-1;i++){
		if(p1->next!=NULL) p1=p1->next;
		else return NULL;    // 注意陷阱:一定要保证链表长度大于k 
	}
	p2=pListHead;
	while(p1->next!=NULL){
		p1=p1->next;
		p2=p2->next;
	}
	return p2;
}
int main() {
	
	return 0;
}
相关题目:

求链表的中间节点。如果链表中的节点总数为奇数,则返回中间节点;如果节点总数是偶数,则返回中间两个节点的任意一个。为了解决这个问题,我们也可以定义两个指针,同时从链表的头节点出发,一个指针一次走一步,另一个指针一次走两步。当走得快的指针走到链表的末尾时,走得慢的指针正好在链表的中间。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
struct ListNode{
	int value;
	ListNode* next;
};
ListNode* FindMidOfList(ListNode* pListHead){
	if(pListHead==NULL){
		return NULL;
	}
	ListNode* p1=pListHead;
	ListNode* p2=pListHead;
	while(p2->next!=NULL){
		p1=p1->next;
		p2=p2->next;
		if(p2->next!=NULL) p2=p2->next;
		else break;
	}
	return p1;
}
int main() {
	
	return 0;
}
发布了42 篇原创文章 · 获赞 43 · 访问量 1070

猜你喜欢

转载自blog.csdn.net/qq_35340189/article/details/104399471