题⽬描述

输⼊⼀个链表,输出该链表中倒数第k个结点。

例如输⼊{1,2,3,4,5} , 2 时,对应的链表结构如下图所示:

其中蓝⾊部分为该链表的最后2 个结点,所以返回倒数第2 个结点(也即结点值为4 的结点)即可,系统会打印后⾯所有的节点来⽐较。

示例1

输⼊:{1,2,3,4,5},2

返回值:{4,5}

说明:返回倒数第2个节点4,系统会打印后⾯所有的节点来⽐较。

示例2

输⼊:{2},8

返回值:{}

思路及解答

两次遍历法

  1. 第一次遍历计算链表长度n
  2. 第二次遍历到第n-K+1个节点(即倒数第K个节点)
  3. 如果K大于链表长度,返回null
public ListNode findKthToTail(ListNode head, int k) {
if (head == null || k <= 0) return null; // 第一次遍历计算链表长度
int length = 0;
ListNode current = head;
while (current != null) {
length++;
current = current.next;
} // 检查k是否有效
if (k > length) return null; // 第二次遍历找到目标节点
current = head;
for (int i = 0; i < length - k; i++) {
current = current.next;
} return current;
}
  • 时间复杂度​:O(n),需要遍历链表两次
  • 空间复杂度​:O(1),只使用了固定数量的指针

双指针法(推荐)

快慢双指针,先让第1 个指针先⾛k 步,然后第2 个指针开始⾛,⽽且两个指针⼀起⾛,直到第⼀个指针⾛到最后的位置。

  1. 使用快慢两个指针,快指针先移动K步
  2. 然后两个指针同步移动,当快指针到达末尾时,慢指针正好指向倒数第K个节点
  3. 如果快指针在移动K步前到达末尾,说明K大于链表长度

public ListNode findKthToTail(ListNode head, int k) {
if (head == null || k <= 0) return null; ListNode fast = head;
ListNode slow = head; // 快指针先移动k步
for (int i = 0; i < k; i++) {
if (fast == null) return null; // k大于链表长度
fast = fast.next;
} // 同步移动两个指针
while (fast != null) {
fast = fast.next;
slow = slow.next;
} return slow;
}
  • 时间复杂度​:O(n),只需遍历链表一次
  • 空间复杂度​:O(1),使用了两个指针

栈辅助法(空间换时间)

  1. 将所有节点压入栈
  2. 弹出K个节点,最后一个弹出的即为所求
  3. 如果栈中节点不足K个,返回null
public ListNode findKthToTail(ListNode head, int k) {
if (head == null || k <= 0) return null; Stack<ListNode> stack = new Stack<>();
ListNode current = head; // 所有节点入栈
while (current != null) {
stack.push(current);
current = current.next;
} // 检查k是否有效
if (k > stack.size()) return null; // 弹出k个节点
ListNode result = null;
for (int i = 0; i < k; i++) {
result = stack.pop();
} return result;
}
  • 时间复杂度​:O(n),需要遍历链表两次(入栈和出栈)
  • 空间复杂度​:O(n),需要额外栈空间存储所有节点

递归回溯法

  1. 递归遍历到链表末尾
  2. 回溯时计数,当计数等于K时返回当前节点
  3. 使用全局变量或包装类传递计数
private int count = 0;

public ListNode findKthToTail(ListNode head, int k) {
if (head == null) return null; ListNode node = getKthFromEnd(head.next, k);
count++; if (count == k) {
return head;
}
return node;
}
  • 时间复杂度​:O(n),需要完整遍历链表
  • 空间复杂度​:O(n),递归栈空间开销

方法对比与总结

方法 时间复杂度 空间复杂度 优点 缺点
两次遍历法 O(n) O(1) 实现简单 需要两次遍历
双指针法 O(n) O(1) 一次遍历,效率高 边界条件需仔细处理
栈辅助法 O(n) O(n) 实现直观 空间开销大
递归回溯法 O(n) O(n) 展示递归思想 空间效率低

剑指offer-14、链表中倒数第k个结点的更多相关文章

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

    14. 链表中倒数第 k 个结点 题目描述 输入一个链表,输出该链表中倒数第k个结点 法一:快慢指针 快指针先走 k 步,等快指针到达尾部时,慢指针所指结点即是倒数第 k 个结点 public cla ...

  2. 剑指Offer 14. 链表中倒数第k个结点 (链表)

    题目描述 输入一个链表,输出该链表中倒数第k个结点. 题目地址 https://www.nowcoder.com/practice/529d3ae5a407492994ad2a246518148a?t ...

  3. [剑指Offer] 14.链表中倒数第k个结点

    [思路]利用两个相隔为k-1个结点的指针进行遍历,当后一个指针移到末尾时,前一个指针就是要求的结点. /* struct ListNode { int val; struct ListNode *ne ...

  4. 剑指Offer:链表中倒数第k个结点【22】

    剑指Offer:链表中倒数第k个结点[22] 题目描述 输入一个链表,输出该链表中倒数第k个结点. 解题思考 我们定义两个指针L和R,R事先移动K-1个位置,然后两者同时往后移动直到遇到R的下个节点为 ...

  5. [剑指offer] 14. 链表中倒数第K个节点+翻转+逆序打印+合并两个排序链表 + 链表相交(第一个公共节点) (链表)

    题目描述 输入一个链表,输出该链表中倒数第k个结点. 思路:  两个指针,起始位置都是从链表头开始,第一个比第二个先走K个节点,当第一个走到链表尾时,第二个指针的位置就是倒数第k个节点.(两指针始终相 ...

  6. 【Java】 剑指offer(22) 链表中倒数第k个结点

    正文 本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的 ...

  7. Go语言实现:【剑指offer】链表中倒数第k个结点

    该题目来源于牛客网<剑指offer>专题. 输入一个链表,输出该链表中倒数第k个结点. Go语言实现: type ListNode struct { Val int Next *ListN ...

  8. 剑指offer:链表中倒数第k个结点

    问题描述 输入一个链表,输出该链表中倒数第k个结点. 解题思路 两个指针都指向头结点,第一个指针先移动k-1个结点,之后两指针同时移动,当第一个指针到链表尾的时候,第二个指针刚好指向倒数第k个结点. ...

  9. 剑指offer例题——链表中倒数第K个结点

    题目描述 输入一个链表,输出该链表中倒数第k个结点. 编程过程 此处采用两个指针依次后移的方法来求解,首先,用一个指针移到第k个位置,之后将第二个指针放在第一位,与第二个指针一同移动,当第二个指针移动 ...

  10. 《剑指offer》链表中倒数第k个结点

    一.题目描述 输入一个链表,输出该链表中倒数第k个结点. 二.输入描述 一个链表 三.输出描述 链表的倒数第k个结点 四.牛客网提供的框架 /* struct ListNode { int val; ...

随机推荐

  1. Python全栈应用开发利器Dash 3.x新版本介绍(2)

    更多Dash应用开发干货知识.案例,欢迎关注"玩转Dash"微信公众号 大家好我是费老师,在上一期文章中,我们针对Python生态中强大且灵活的全栈应用开发框架Dash,介绍了其3 ...

  2. FreeRTOS 学习笔记(持续更新)

    抢占式调度: 高优先级的可以优先运行,即使以及有低优先级的在运行,会先停止低的再运行高的(优先级按数字大小分大小) 高优先级任务不停止,低优先级的任务无法运行 被抢占的任务会进入就绪态 时间片调度: ...

  3. asp.net mvc 获取请求服务器信息

    HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] /// <summary>        /// ...

  4. mermaid与marked结合使用

    前提 两者都很强大,但是两者结合,存在问题,目前网上无解. 以下两种版都需要在index.html 即入口页面添加一个元素 <body> <div id="root&quo ...

  5. Skill Discovery | METRA:让策略探索 state 的紧凑 embedding space

    论文标题:METRA: Scalable Unsupervised RL with Metric-Aware Abstraction ICLR 2024 Oral. arxiv:https://arx ...

  6. vue05-REST 请求

    异步REST /* * @Author: caijw * @Date: 2018-02-23 14:07:30 * @Last Modified by: caijw * @Last Modified ...

  7. CloudQuery v1.4.0 发布 | 全栈数据管控平台的新起点

    Hello,社区的小伙伴们,好久不见!经过一个多月努力,CloudQuery v1.4.0 终于和大家见面了! v1.4.0 版本的新功能包括:调度中心模块.DTS (Database Tools S ...

  8. JSP总结(经典)

    摘自:https://www.cnblogs.com/cyjch/archive/2012/03/28/2420798.html day1 JSP 定义:     1)Java Server Page ...

  9. 基于阿里云RDS SQL Server + 函数计算 + 通义AI构建智能销售分析平台Demo

      随着云原生技术和AI能力的不断成熟,如何将传统数据库.无服务器计算和人工智能有机结合,构建现代化的数据分析平台,并借助阿里云提供的基础组件构建应用.本文基于微软经典的WorldWideImport ...

  10. P2910 [USACO08OPEN] Clear And Present Danger S (Floyd算法)

    题目链接:https://www.luogu.com.cn/problem/P2910 题解 #include <bits/stdc++.h> using namespace std; c ...