《程序员面试金典》(第六版)习题:仅为记录一下以加强印象,不为商业用途,如有侵权请联系删除。以下源码和解释参考了书中源码以及这里:https://github.com/alexhagiopol/cracking-the-coding-interview。源码中节点以及功能函数定义参见这里:2.1 移除重复节点
//迭代法//
template <typename T>
const SinglyLinkedNode<T>* returnKthToLast(const SinglyLinkedNode<T>* head, int k)
{
if (head == nullptr)
return nullptr;
const SinglyLinkedNode<T>* slowRunner = head;
const SinglyLinkedNode<T>* fastRunner = head;
while(k > 0)
{
if (fastRunner == nullptr)
return nullptr;
fastRunner = fastRunner->getNext();
k--;
}
while (fastRunner != nullptr)
{
slowRunner = slowRunner->getNext();
fastRunner = fastRunner->getNext();
}
return slowRunner;
}
迭代算法,首先设置两个指针,一个指向链表的第一个节点,另一个指向从第一个节点开始的第K个节点。K为1表示倒数第一个节点,以此类推。接下来两个指针同步向后移动直到后一个指针为空,此时前一个指针指向的元素为倒数第K个节点。
该算法的时间复杂度为O(N),空间复杂度为O(1)。
//递归算法//
template <typename T>
const SinglyLinkedNode<T>* returnKthToLast(const SinglyLinkedNode<T>* head, int k, int &i)
{
if (head == nullptr)
return nullptr;
SinglyLinkedNode<T>* nd=returnKthToLast(head->getNext(), k, i);
i=i+1;
if(k==i)
{
return head;
}
return nd;
}
递归算法中参数I被初始化为0,它是一个引用,它用来对倒数的节点进行计数。递归过程如图1所示。
递归算法的时间复杂度为O(n),空间复杂度为O(n),n为链表中节点的个数。