程序员面试金典 2.2

本文介绍两种高效算法来寻找单链表中倒数第K个元素,包括递归方法和迭代方法,使用快慢指针技巧实现O(N)时间复杂度和O(1)空间复杂度。

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;
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值