方法一:先遍历链表得到链表的节点数目,即可得到倒数最后K个节点是正数第几个节点。

时间复杂度:o(n)

空间复杂度:o(1)

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pHead, int k) {
        //特殊情况处理;链表为空和k不大于0两种情况
        if (pHead == nullptr || k <= 0)
            return nullptr;

        ListNode* pnode = pHead;
        ListNode* temp = pHead;
        int length = 0;
	  	//得到链表长度
        while (pnode) {
            pnode = pnode->next;
            length++;
        }
	  	//如果k大于链表长度,返回nullptr
        if (k > length) {
            return nullptr;
        } else {
            for(int i = 0; i < length - k; i++) {
                temp = temp->next;
            }
            return temp;
        }
    }
};

方法二:双指针求解

设置两个指针都等于头结点,一个指针先走k步;然后两个指针同时移动,当快指针指向nullptr,慢指针到达倒数第k个节点。

时间复杂度:o(n)

空间复杂度:o(1)

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pHead, int k) {
	  	//特殊情况处理;链表为空和k不大于0两种情况
        if (pHead == nullptr || k <= 0)
            return nullptr;

        ListNode* slow = pHead;
        ListNode* fast = pHead;
		//快指针移动K位
        for (int i = 0; i < k; i++) {
            if (fast == nullptr)
                return nullptr;
            else
                fast = fast->next;
        }
	  	//两个指针同时移动直到快指针指向到达链表尾部
        while (fast) {
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }
};

方法三:使用栈求解。利用栈先进后出的特点,倒数第K个节点即是第K个出栈的节点。

时间复杂度:o(n)

空间复杂度:o(n)

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pHead, int k) {
	  	//特殊情况处理;链表为空和k不大于0两种情况
        if (pHead == nullptr || k < 0)
            return nullptr;

        stack<ListNode*> sk;
        ListNode* pnode = pHead;
        while(pnode != nullptr) {
            sk.push(pnode);
            pnode = pnode->next;
        } 
	  	//如果K大于链表数目
        if (k > sk.size()) {
            return nullptr;
        } else {
            while(k-1) {
                sk.pop();
                k--;
            }
            return sk.top();
        }
    }
};