链表中倒数第k个节点

问题:输入一个链表,输出该链表中倒数第k个结点。

思路1:一个比较笨的方法是遍历链表的节点,统计从当前节点到末尾的节点数,当节点数恰好等于k时,当前节点就是链表中倒数第k个节点。这种方法的时间复杂度是O(n^2),比较坏的情况是:链表很长,且k很小。

C++

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        while (pListHead) {
            if (countNodes(pListHead) == k) return pListHead;
            pListHead = pListHead->next;
        }
        return NULL;
    }
    
    int countNodes(ListNode* head) {
        int ret = 0;
        while (head) {
            ret++;
            head = head->next;
        }
        return ret;
    }
};

思路2:先遍历一次链表,记下链表的长度len;第二次遍历链表,走到len-k+1的位置,就是倒数第k个节点。

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        int len = 0;
        ListNode *cur = pListHead;
        while (cur) {
            len++;
            cur = cur->next;
        }
        cur = pListHead;
        int cnt = 0;
        while (cur) {
            cnt++;
            if (cnt == len-k+1) return cur;
            cur = cur->next;
        }
        return NULL;
    }
};

思路3:维护两个指针:主指针mainPtr和从指针refPtr,开始都指向链表头部。先将从指针移到第k个节点,然后两个指针同时往前走,当从指针走到最后一个节点时,主指针所处的位置就是链表倒数第k个节点。这个方法比较巧妙,只需遍历一次链表。

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if (!pListHead || k <= 0) return NULL;
        ListNode *mainPtr = pListHead, *refPtr = pListHead;
        for (int i = 1; i < k; ++i) {
            refPtr = refPtr->next;
            if (!refPtr) return NULL;
        }
        while (refPtr->next) {
            mainPtr = mainPtr->next;
            refPtr = refPtr->next;
        }
        return mainPtr;
    }
};
posted @ 2017-02-07 23:21  mioopoi  阅读(282)  评论(0编辑  收藏  举报