[面试问题]
编写一个函数,在一次传递中从单个链接的整数列表的尾部(或结尾)返回第5个元素,然后提供一组针对该函数的测试用例。
它类似于问题:How to find nth element from the end of a singly linked list?,但我还有一个额外要求,即我们应该只遍历一次链表。
这是我的解决方案:
struct Lnode
{
int val;
Lnode* next;
Lnode(int val, Lnode* next=NULL) : val(val), next(next) {}
};
Lnode* kthFromTail(Lnode* start, int k)
{
static int count =0;
if(!start)
return NULL;
Lnode* end = kthFromTail(start->next, k);
if(count==k) end = start;
count++;
return end;
}
我只使用一次隐式递归堆栈遍历链表。另一种方法可能是有两个指针:快速和慢速,快速的指针比慢指针快。一个似乎更好?我认为具有两个指针的解决方案将很复杂,例如:奇数长度列表,甚至长度列表,k>列表的长度等。这一个使用递归是干净的,涵盖所有这些情况。
答案 0 :(得分:5)
2指针解决方案不符合您的要求,因为它遍历列表两次。
你的内存使用更多 - 确切地说是O(n)。您正在创建一个等于列表中项目数的递归堆栈,这远非理想。
从最后一项找到第k个...
更好的(单遍历)解决方案 - Circular buffer:
使用O(k)额外内存。
有一个长度为k的数组。
对于每个元素,在数组的下一个位置插入(使用环绕)。
最后,只需返回数组中下一个位置的项目。
双指针解决方案:
遍历列表两次,但仅使用O(1)额外内存。
从头开始p 1 和p 2 。
增加p 1 k次。
而p 1 不在最后 增量p 1 和p 2
p 2 指向最后一个元素的第k个。
答案 1 :(得分:0)
'n' is user provided value. eg, 5 from last.
int gap=0 , len=0;
myNode *tempNode;
while (currNode is not NULL)
{
currNode = currNode->next;
gap = gap+1;
if(gap>=n)
tempNode = currNode;
}
return tempNode;