第22题:链表中倒数第k个结点

题目描述

题目:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。

 

考点

鲁棒性:指针为nullptr,链表节点数少于K,输入的K为0

双指针遍历:只用遍历一次,复杂度O(n)

unsigned int: 为0的时候,k-1会变成0xFFFFFFFFF,4294967295,进入无限死循环

 

第一遍

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
	//1.鲁棒性检查,nullptr链表,k=0的情况,返回nullptr
	if (pListHead == nullptr || k == 0)
		return nullptr;

	//2.定义双指针,第一个指向头节点,第二个指向nullptr
	ListNode* first = pListHead;
	ListNode* second = nullptr;

	//3.第一个指针向前走k-1步
	for (int i = 0; i < k-1; i++)
	{		
		//3.1如果k比链表节点大,返回nullptr
		if (first->m_pNext == nullptr)
			return nullptr;
		//3.2 否则,向前走一步
		else
			first = first->m_pNext;
	}
	
	//4.第二个指针开始走
	second = pListHead;

	//5.当第一个指针直到最后一个节点时,第二个指针指向倒数第k个节点
	while (first->m_pNext!=nullptr)
	{
		first = first->m_pNext;
		second = second->m_pNext;
	}

	//6.返回第二个指针的值
	return second;
}

 注意:

//3.第一个指针向前走k-1步
    for (int i = 0; i < k-1; i++)
    {        
        //3.1如果k比链表节点大,返回nullptr
        if (first->m_pNext == nullptr)
            return nullptr;
        //3.2 否则,向前走一步
        else
            first = first->m_pNext;
    }

要先判断first->m_pNext是否存在,再往后走一个


第二遍

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        //1.鲁棒性检查
        if(pListHead==nullptr||k==0)
            return nullptr;
        
        //2.定义双指针
        ListNode* first=pListHead;
        ListNode* second=nullptr;
        
        //3.第一指针先走K-1步
        for(int i=0;i<k-1;i++)
        {
            //3.1 鲁棒性检查,如果k大于链表节点,返回nullptr
            if(first->next==nullptr)
                return nullptr;
            //3.2 否则往下走一步
            else
                first=first->next;
        }
        
        //4.第二个指针开始走
        second = pListHead;
        
        //5.直到第一个指针走到最后一个节点,第二个指针就是倒数第K个数,他们的距离是k-1
        while(first->next!=nullptr)
        {
            first=first->next;
            second=second->next;
        }
        
        //6.返回这时的第二个指针
        return second;
    }
};

相关题目

求链表的中间节点,如果链表中的节点总数为奇数,则返回中间节点;如果节点总数是偶数,则返回中间两个节点的任意一个。

为了解决这个问题,我们也可以定义两个指针,同时从链表的头节点出发,一个指针一次走一步,另一个指针一次走两步。
当走得快的指针走到链表的末尾时,走得慢的指针正好在链表的中间。 

struct ListNode {
    int val;
    ListNode *next;

};

ListNode* FindIntermediateNode(ListNode* pHead) {
    if (pHead ==nullptr) 
        return nullptr;

    ListNode* pFast = pHead;
    ListNode* pSlow = pHead;

    while (pFast != NULL && pFast->next != NULL) {
        pFast = pFast->next->next;
        pSlow = pSlow->next;
    }

    return pSlow;
}

 

posted @ 2019-02-06 18:45 lightmare 阅读(...) 评论(...) 编辑 收藏