牛客题解 | 链表中倒数最后k个结点

news/2025/2/21 10:14:23/文章来源:https://www.cnblogs.com/wc529065/p/18728705

题目

题目链接

题目的主要信息:
  • 一个长度为\(n\)的链表,返回原链表中从倒数第k个节点至尾节点的全部节点
  • 如果该链表长度小于k,请返回一个长度为 0 的链表
举一反三:

学习完本题的思路你可以解决如下题目:

BM4.合并有序链表

BM5.合并k个已排序的链表

BM6.判断链表中是否有环

BM7.链表中环的入口节点

BM9.删除链表的倒数第n个节点

BM10.两个链表的第一个公共节点

BM13.判断一个链表是否为回文结构

BM14.链表的奇偶重排

方法一:快慢双指针(推荐使用)

知识点:双指针

双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针(特殊情况甚至可以多个),两个指针或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而达到我们需要的目的。

思路:

我们无法逆序遍历链表,就很难得到链表的倒数第\(k\)个元素,那我们可以试试反过来考虑,如果当前我们处于倒数第\(k\)的位置上,即距离链表尾的距离是\(k\),那我们假设双指针指向这两个位置,二者同步向前移动,当前面个指针到了链表头的时候,两个指针之间的距离还是\(k\)。虽然我们没有办法让指针逆向移动,但是我们刚刚这个思路却可以正向实施。

具体做法:

  • step 1:准备一个快指针,从链表头开始,在链表上先走\(k\)步。
  • step 2:准备慢指针指向原始链表头,代表当前元素,则慢指针与快指针之间的距离一直都是\(k\)
  • step 3:快慢指针同步移动,当快指针到达链表尾部的时候,慢指针正好到了倒数\(k\)个元素的位置。

图示:
alt

Java实现代码:

import java.util.*;
public class Solution {public ListNode FindKthToTail (ListNode pHead, int k) {int n = 0;ListNode fast = pHead; ListNode slow = pHead;//快指针先行k步for(int i = 0; i < k; i++){  if(fast != null)fast = fast.next;//达不到k步说明链表过短,没有倒数kelse return slow = null;}//快慢指针同步,快指针先到底,慢指针指向倒数第k个while(fast != null){ fast = fast.next;slow = slow.next;}return slow;}
}

C++实现代码:

class Solution {
public:ListNode* FindKthToTail(ListNode* pHead, int k) {ListNode* fast = pHead; ListNode* slow = pHead;//快指针先行k步for(int i = 0; i < k; i++){  if(fast != NULL)fast = fast->next;//达不到k步说明链表过短,没有倒数kelse return slow = NULL;}//快慢指针同步,快指针先到底,慢指针指向倒数第k个while(fast != NULL){ fast = fast->next;slow = slow->next;}return slow;}
};

Python代码实现:

class Solution:def FindKthToTail(self , pHead , k ):fast = pHeadslow = pHead#快指针先行k步for i in range(0,k): if fast != None:fast = fast.next#达不到k步说明链表过短,没有倒数kelse: return None#快慢指针同步,快指针先到底,慢指针指向倒数第k个while fast:fast = fast.nextslow = slow.nextreturn slow

复杂度分析:

  • 时间复杂度:\(O(n)\),总共遍历\(n\)个链表元素
  • 空间复杂度:\(O(1)\),常数级指针变量,无额外辅助空间使用
方法二:先找长度再找最后k(扩展思路)

思路:

链表不能逆向遍历,也不能直接访问。但是对于倒数第\(k\)个位置,我们只需要知道是正数多少位还是可以直接遍历得到的。

具体做法:

  • step 1:可以先遍历一次链表找到链表的长度。
  • step 2:然后比较链表长度是否比\(k\)小,如果比\(k\)小返回一个空节点。
  • step 3:如果链表足够长,则我们从头节点往后遍历\(n-k\)次即可找到所求。

Java实现代码:

import java.util.*;
public class Solution {public ListNode FindKthToTail (ListNode pHead, int k) {int n = 0;ListNode p = pHead;//遍历链表,统计链表长度while(p != null){n++;p = p.next;}//长度过小,返回空链表if(n < k) return null;p = pHead;//遍历n-k次for(int i = 0; i < n - k; i++) p = p.next;return p;}
}

C++实现代码:

class Solution {
public:ListNode* FindKthToTail(ListNode* pHead, int k) {int n = 0;ListNode* p = pHead;//统计链表长度while(p != NULL){ n++;p = p->next;}//长度过小,返回空链表if(n < k) return NULL;p = pHead;//遍历n-k次for(int i = 0; i < n - k; i++) p = p->next;return p;}
};

Python代码实现:

class Solution:def FindKthToTail(self , pHead , k ):n = 0p = pHead#统计链表长度while p: n = n + 1p = p.next#长度过小,返回空链表if n < k: return Nonep = pHead#遍历n-k次for i in range(n-k): p = p.nextreturn p

复杂度分析:

  • 时间复杂度:\(O(n)\),最坏情况下两次遍历链表\(n\)个元素
  • 空间复杂度:\(O(1)\),常数级指针变量,无额外辅助空间使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/887490.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

打造专属任务管理利器:智慧工具私有化部署策略与实践

智慧任务管理工具私有化是指将智慧任务管理工具部署在组织内部的私有服务器或云环境中,以确保数据的安全性、隐私性和完全控制权。以下是对智慧任务管理工具私有化的详细解析: 一、私有化的优势 ● 数据安全:私有化部署确保所有数据存储在组织内部的服务器或私有云中,避免数…

牛客题解 | 设计LFU缓存结构

牛客输入输出题单题解题目 题目链接 题目的主要信息:实现LFU的set与get函数,且复杂度为\(O(1)\) 每次调用这两个函数会给一个频率赋值,超出长度则移除频率最少的,若有频率相同,则移除访问时间最早的举一反三: 学习完本题的思路你可以解决如下题目: BM100. 设计LRU缓存结…

牛客题解 | 设计LRU缓存结构

牛客输入输出题单题解题目 题目链接 题目的主要信息:实现LRU缓存的模拟结构,包括加入函数set,访问函数get 结构有长度限制,加入新数时,超出长度则需要删除最不常访问的,其中set与get都访问 两个函数都是\(O(1)\)举一反三: 学习完本题的思路你可以解决如下题目: BM101. …

牛客题解 | 编辑距离(一)

牛客输入输出题单题解题目 题目链接 题目主要信息:给定两个长度可能不同的字符串,可以对第一个字符串增删改字符 求增删改的最少次数,让第一个字符串变成第二个字符串 字符串中只出现大小写字母举一反三: 学习完本题的思路你可以解决如下题目: BM65 最长公共子序列(二) BM6…

网上学习导航

推荐一个网上学习好玩的地方 学吧导航 网站截图

解决 windows 安装centos7虚拟机 每隔一段时间 虚拟机ip会变动 怎么固定他的ip

查看当前虚拟机的ip地址:我的是192.168.217.136然后获取到网关ip:打开 VMware Workstation,选中你要设置的虚拟机,点击 “编辑” -> “编辑虚拟机设置”。通过ipconfig 可以看到我的是ens160 我的文件就是 ifcfg-ens160 ,然后使用以下命令进行操作sudo nano /etc/sysco…

牛客题解 | 求二叉树的层序遍历

牛客输入输出题单题解题目 题目链接 题目的主要信息:将给定二叉树按行从上到下、从左到右的顺序输出 输出到一个二维数组中,数组中每行就是二叉树的一层举一反三: 学习完本题的思路你可以解决如下题目: BM27. 按之字形顺序打印二叉树 BM35. 判断是否是完全二叉树 方法一:非…

牛客题解 | 没有重复项数字的全排列

牛客输入输出题单题解题目 题目链接 题目主要信息:给定一个数组,求这组数字的全排列 数组无重复元素 以数字在数组中的位置靠前为优先级,按字典序排列输出举一反三: 学习完本题的思路你可以解决如下题目: BM56. 有重复项数字的全排列 BM58. 字符串的排列 BM60. 括号生成 递…

牛客题解 | 最长无重复子数组

牛客输入输出题单题解题目 题目链接 题目主要信息:题目给定一个数组,要找到其中最长的无重复的子数组的长度 子数组必须是数组中连续的一段举一反三: 学习完本题的思路你可以解决如下题目: BM90. 最小覆盖子串 方法:滑动窗口(推荐使用) 知识点1:滑动窗口 滑动窗口是指在数…

牛客题解 | 最长的括号子串

牛客输入输出题单题解题目 题目链接 题目主要信息:一个长度为\(n\)的仅包含左右括号的字符串 计算最长的格式正确的括号子串的长度举一反三: 学习完本题的思路你可以解决如下题目: BM65 最长公共子序列(二) BM66.最长公共子串 BM71.最长上升子序列(一) BM73 最长回文子串 BM…

牛客题解 | 最长公共前缀

牛客输入输出题单题解题目 题目链接 题目主要信息:给定一个字符串数组,其中有n个字符串,求所有字符串的最长公共前缀 公共前缀是指所有字符串都共有的前面部分的子串,从第一个字符开始举一反三: 学会了本题的思路,你将可以解决类似的字符串问题: BM83. 字符串变形 BM85. …

牛客题解 | 旋转数组

牛客输入输出题单题解题目 题目链接 题目主要信息:一个长度为\(n\)的数组,将数组整体循环右移\(m\)个位置(\(m\)可能大于\(n\)) 循环右移即最后\(m\)个元素放在数组最前面,前\(n-m\)个元素依次后移 不能使用额外的数组空间举一反三: 学习完本题的思路你可以解决如下题目:…