剑指offer代码解析——面试题15求链表中倒数第K个结点
时间:2022-05-03
本文章向大家介绍剑指offer代码解析——面试题15求链表中倒数第K个结点,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
算法的分析过程均在代码注释中:
/**
* 题目:输入一个单链表,输出该链表从后往前的第k个数。
* PS:从后往前数时从1开始计数。
* @author 柴毛毛大闲人
*/
public class TailK {
/**
* 分析:要寻找倒数第k个数,很自然想到的方法是:从末尾向前找第k个数。
* 然而这种方法面临两个问题:1.我们无法直到单链表的末尾在哪儿,2.我们无法从后向前遍历单链表。
* 为了解决上述两个问题,我们首先想到的方法是:遍历两次单链表,第一次求得单链表的长度n,第二次遍历到第n-k个元素停止即可。
* 代码如下:
*/
//使用全局变量result表示函数运行结果
static boolean result = true;
/**
* @param first 单链表的首结点
* @param k 要找的倒数第几个元素
* @return 返回倒数第K个值
*/
public static int getTailK(Node<Integer> first,int k){
//若链表为空
if(first==null){
System.out.println("链表为空!");
result = false;
return 0;
}
//若k<=0
if(k<1){
System.out.println("k不能小于1!");
result = false;
return 0;
}
//计算链表长度
int length = 1;
Node<Integer> p = first;
while(p.next!=null){
length++;
p = p.next;
}
//若k比链表还长
if(length<k){
System.out.println("k="+k+"超过了链表长度!");
result = false;
return 0;
}
//遍历链表,遍历到第n-k个元素结束
Node<Integer> q = first;
for(int i=0;i<length-k;i++)
q = q.next;
return q.data;
}
/**
* 上述方法能解决问题,但需要遍历链表两次,能否有更高效的办法?
* 可以使用两个指针i和j,指针i从头开始先走k步,然后j指向第一个结点,接下来保持i和j之间的距离,当j走到尾时,i指向的结点就是倒数第k个结点。
* 代码如下:
*/
public static int getTailK_modify(Node<Integer> first,int k){
//若链表为空
if(first==null){
System.out.println("链表为空!");
result = false;
return 0;
}
//若k<=0
if(k<1){
System.out.println("k不能小于1!");
result = false;
return 0;
}
//定义两个指针p和q,p指向头结点,q指向第k个结点
Node<Integer> p = first;
Node<Integer> q = first;
//将q指向第k个结点
for(int i=0;i<k-1;i++){
//若q还没指向第k个结点,但q已经是最后一个结点,则说明k超过了链表长度
if(q.next==null){
System.out.println("k="+k+"超过了链表长度!");
result = false;
return 0;
}
q = q.next;
}
//p和q分别向后移动,直到q走到链表末尾为止
while(q.next!=null){
p = p.next;
q = q.next;
}
return p.data;
}
/**
* 测试
*/
public static void main(String[] args){
Node<Integer> node1 = new Node<Integer>();
Node<Integer> node2 = new Node<Integer>();
Node<Integer> node3 = new Node<Integer>();
Node<Integer> node4 = new Node<Integer>();
node1.data = 1;
node2.data = 2;
node3.data = 3;
node4.data = 4;
node1.next = node2;
node2.next = node3;
node3.next = node4;
System.out.println(getTailK_modify(node1,11));
}
}
/**
* 定义结点
*/
class Node<T>{
public T data;
public Node<T> next;
}
- 简单的实现Javascript的MVC
- 谷歌再出黑科技!人工智能模拟的人声和真人几乎难以分辨
- 【Scikit-Learn 中文文档】高斯混合模型 - 无监督学习 - 用户指南 | ApacheCN
- “E+单拼”组合域名eqi.com小六位结拍
- ASP.NET Core中的依赖注入(3): 服务的注册与提供
- 【Scikit-Learn 中文文档】使用 scikit-learn 介绍机器学习 | ApacheCN
- 哈萨比斯:2018年AI最大突破在生物或化学领域
- ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【总体设计 】
- ASP.NET MVC的View是如何被呈现出来的?[设计篇]
- Python大牛告诉你一行代码能干什么?神奇
- 谷歌最新人工智能研究:仅利用稀疏轮廓位置“重构”图像
- DATUM和BigchainDB
- MySQL主从复制的实现过程
- 使用dict和set
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Struts2笔记
- Vue Router实现路由嵌套单页面展示
- 排障集锦:九九八十一难之第九难!mysql备份恢复路上的小插曲
- jQuery限制复选框checkbox的选中次数
- jQuery点击切换增加和删除class类
- Vue使用props和emit父子组件通信
- 听说Mysql你很豪横?-------------呕心沥血深入解析mysql备份与恢复!!!
- 排障集锦:九九八十一难之第十难!mysq备份恢复,Could not read entry at offset *: Error in log format or read error.
- Vue使用ref父子组件通信
- 听说Mysql你很豪横?-------------MySQL5.7主从同步
- 听说Mysql你很豪横?-------------MySQL5.7主从复制!读写分离!
- Vue兄弟组件传值
- Vue设置浏览器的标题title和图标icon
- VantUI封装自定义Tabbar路由跳转
- 听说Mysql你很豪横?-------------分分钟带你玩转SQL高级查询语句(常用查询,正则表达式,运算符)