剑指offer——14.链表中倒数第k个结点

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/N1neDing/article/details/82716481

题目描述:

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

注意事项:

应注意代码鲁棒性,当头节点为空时,k小于等于0,k大于节点总数目时,都应进行处理,以避免程序崩溃。

解题思路1:

先遍历一次计算出链表中节点总数目num,然后倒数第k个节点就是正数第num-k+1个节点。

参考源码1:

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
    {  
            if(pListHead == NULL || k <= 0) return NULL;
            int num = 0;
            ListNode* tmp = pListHead;
            while(tmp != NULL)
            {
                    num++;
                    tmp = tmp->next;
            }
            if(num < k) return NULL;
            int pos = num - k + 1;
            for(int i = 1;i  < pos;i++)
            {
                    pListHead = pListHead->next;
            }
            return pListHead;
    }  
};

解题思路2:

分别设立两个前后指针,前方指针在后方指针前k-1个位置,当前方指针到达尾节点时,后方指针所在位置即为倒数第k个节点。

参考源码2:

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
    {  
            if(pListHead == NULL || k <= 0) return NULL;
            ListNode* fast = pListHead;
            ListNode* slow = pListHead;
            for(int i = 1;i < k;i++)
            {
                    fast = fast->next;
                    if(fast == NULL) return NULL;
            }
            while(fast->next != NULL)
            {
                    fast = fast->next;
                    slow = slow->next;
            }
            return slow;
    }  
};

相关题目:

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

解题思路:

需要首先判断链表是否是环状结构,再求中间节点,同样是使用一前一后两个节点的操作。前方节点每次移动两次,后方节点每次移动一次,(这里需要注意,除了(fast != NULL)这个条件,一定要加上(fast->next != NULL)的判断条件,因为fast每次移动两次,当移动到结尾的时候,再连续向后移动两次会发生错误),当前方节点移动到结尾时,后方节点则是中间节点。

参考源码:

#include <iostream>
using namespace std;
struct ListNode
{
        int val;
        struct ListNode* next;
        ListNode(int x):val(x),next(NULL)
        {
        }
};
class Solution
{
        public:
        ListNode* FindMid(ListNode* pHead)
        {
                if(pHead == NULL) return NULL;
                if(pHead->next == NULL) return NULL;
                ListNode* fast = pHead;
                ListNode* slow = pHead;
                //判断是否是环状链表
                bool judge = false;
                while(fast != NULL && fast->next != NULL)
                {
                        fast = fast->next->next;
                        slow = slow->next;
                        if(fast == slow)
                        {
                                judge = true;
                                break;
                        }
                }
                if(judge)
                {
                        return NULL;
                }
                fast = pHead;
                slow = pHead;
                while(fast != NULL && fast->next != NULL)
                {
                        fast = fast->next->next;
                        slow = slow->next;
                }
                return slow;

        }
};
int main()
{
        ListNode* begin = new ListNode(1);
        ListNode* begin1 = new ListNode(2);
        ListNode* begin2 = new ListNode(3);
        ListNode* begin3 = new ListNode(4);
        ListNode* begin4 = new ListNode(5);
        begin->next = begin1;
        begin1->next = begin2;
        begin2->next = begin3;
        begin3->next = begin4;
        Solution s;
        ListNode* res = s.FindMid(begin);
        cout<<res->val<<endl;
        return 0;
}

猜你喜欢

转载自blog.csdn.net/N1neDing/article/details/82716481