Return Kth to Last:返回单链表中倒数第k个元素。
下面会分别使用递归和非递归的方法来解决这道题,一般来说递归的方法写起来更容易,但是效率一般不是最好的,比如这道题递归解法的代码量大约是非递归解法的一半,但是时间复杂度依然是O(N)。
递归解法。这种方法的本质是先遍历到链表尾部,最后再返回的过程中找到第k个。设链表的头为head,要在head的链表中查找倒数第k个元素,就是在head->next的链表中查找倒数第k个元素,递归的结束条件是到达链表末尾。在每一次返回时,将一个计数器加1,这样当计数器为k时,就找到了倒数第k个元素。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
int kthToLast(ListNode* head, int k) {
int iTh = 0;
return doKthToLast(head, k, iTh)->val;
}
private:
ListNode* doKthToLast(ListNode* head, int k, int &iTh)
{
if(head == nullptr) return nullptr;
ListNode* p = doKthToLast(head->next, k, iTh);
iTh++;
if(iTh == k) return head;
return p;
}
};
注:这种解法可能是来自函数式语言,例如Lisp。在《计算机程序的构造和解释》的第二章中,介绍了大量关于list的操作,都是使用这种规约方法。
迭代解法。迭代解法的思想是使用快慢指针。初始化时将两个指针的距离设置为k。当快指针到达链表末尾时,慢指针就是倒数第k个元素。这种解法的时间复杂度为O(N),空间复杂度为O(1)。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
int kthToLast(ListNode* head, int k) {
ListNode* fast = head;
ListNode* slow = head;
for(int i = 0; i < k; i++)
{
fast = fast->next;
}
while(fast != nullptr){
fast = fast->next;
slow = slow->next;
}
return slow->val;
}
};
本文介绍两种高效算法来寻找单链表中倒数第K个元素,包括递归方法和迭代方法,使用快慢指针技巧实现O(N)时间复杂度和O(1)空间复杂度。
1091

被折叠的 条评论
为什么被折叠?



