<手撕链表系列>-链表中倒数第k个结点/找到链表的中间结点

93 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

前言

本系列主要讲解链表的经典题

注:划重点!!必考~

找到链表的中间结点

力扣链接:876. 链表的中间结点 - 力扣(LeetCode) (leetcode-cn.com)

  • 题目描述:

给定一个头结点为 head 的非空单链表,返回链表的中间结点

如果有两个中间结点,则返回第二个中间结点

  • 示例:​编辑
  • 提示:
  • 给定链表的结点数介于 1 和 100 之间
  • 解题思路:
  • 一般的思路:

一个个遍历,得到链表长度,在遍历链表长度的二分之一,就能得到中间结点

  • 高效思路:

  1. 使用两个指针
  2. 一个慢指针每次走一个结点的位置
  3. 一个快指针每次走慢指针的两倍长度
  4. 当快指针走完链表时,而慢指针则恰在链表中间结点位置

注意:链表长度有奇数和偶数两种情况

注:这里我们来实现高效思路

  • 图示:

​编辑

  •  参考代码:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* middleNode(struct ListNode* head){
    //创建快慢指针,快指针走两步,而慢指针走一步(当快指针到尾时,慢指针在中间)
    struct ListNode*slow,*fast;
    slow=fast=head;
    //节点为单数时,快指针走到尾节点(fast下一个节点为NULL则停止)
    //节点为双数时,快指针走到尾节点的下一个节点NULL(fast为NULL则停止)
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

  • 结果:

链表中倒数第k个结点

牛客链接:链表中倒数第k个结点_牛客题霸_牛客网 (nowcoder.com)

  • 题目描述:

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

  • 示例:
  • 解题思路:
  • 一般思路:

遍历链表两次

  • 高效思路:

  1. 使用两个指针
  2. 快指针先走k步
  3. 慢指针再与快指针一起走
  4. 当快指针走完时,慢指针走到倒数第k个结点

注意:k的大小可能超过链表长度这一特殊情况

注:这里我们来实现高效思路

  • 参考代码:
/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

/**
 * 
 * @param pListHead ListNode类 
 * @param k int整型 
 * @return ListNode类
 */
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    //链表不为NULL
    if(pListHead==NULL)
        return NULL;
    struct ListNode* slow=pListHead,*fast=pListHead;
    while(k--)
    {
        //节点数量比k小
        if(fast==NULL)
            return NULL;
        fast=fast->next;
    }
    //fast为NULL则停止
    while(fast)
    {
        fast=fast->next;
        slow=slow->next;
    }
    return slow;
}

  • 结果: