题目描述: 输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如一个链表有6个节点,从头节点开始他们的值依次是1、2、3、4、5、6.这个链表的倒数第3个节点值为4.
解题思路: 主要思路是借助两个迭代器指向的位置,确定倒数第k个节点。
第一步,测试用例:
//1.测试用例
int main(){
//初始化链表,C++中的链表是双向链表。 在此我们默认其为单向的链表。
list<int> List{9, 8, 7, 6, 5, 4, 3, 2, 1};
//保存倒数第k个节点的迭代器
list<int>::iterator result;
//要查找的倒数第K个节点
int k;
cout << "Please enter k: \n";
while(cin >> k){
result = findKToTail(List, k);
if(result != List.end())//判断是否为空
cout << "Result is: " << *result << endl;
else
cout << "Invalid inputs\n";
}
return 0;
}
//2.根据测试用例定义模板函数,输入参数为一个链表和k的值,返回倒数第k个节点的迭代器
template <typename T>
typename list<T>::iterator findKToTail(list<T> &li, int k){//附:以typename为前缀来表示类型,因为iterator依赖名称不是类型
//链表迭代器
list<T>::iterator beg = li.begin(), result = beg;
//3.链表是否为空、k是否大于0、k是否超出了链表的规模
if(beg == li.end() || k <= 0 || k > li.size()) //附:C++迭代器判空不能用NULL,而是用end()(类似于尾部的下一个节点)。即如果li.begin() == li.end(),这个链表为空
return li.end();
//由于默认是单向列表,先将beg从前向后定位至第k个节点
for(auto i = 0; i != k; ++i, ++beg){
}
//因为此时result与beg相差k-1个节点,将两个迭代器同时向后移动,当beg指向链表的末尾时停止移动,result即为倒数第k个节点
while(beg != li.end()){
++beg;
++result;
}
//返回迭代器
return result;
}
整体思路都在注释中描述,此题重点注意的是输入是否合法、边界问题及对此类问题的处理方法;作为一名程序设计人员,应该对问题的考虑更加全面、细心,提前预测有可能出现的令程序崩溃的问题。