找到单链表中的倒数第K个节点,并打印输出节点。两段代码,思路都是相似的。

一、代码1
public class SingleLinkedListDemo {public static void main(String[] args) {//开始测试System.out.println("开始测试... ... ... ... ...");//1.创建节点HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");HeroNode hero3 = new HeroNode(3, "吴用", "智多星");HeroNode hero4 = new HeroNode(4, "公孙胜", "入云龙");HeroNode hero5 = new HeroNode(5, "关胜", "大刀");//2.创建链表SingleLinkedList singlelinkedlist1 = new SingleLinkedList();//输出顺序等于加入顺序//SingleLinkedList singlelinkedlist2 = new SingleLinkedList();//输出顺序按照编号排序//3.将创建好的节点加入到创建好的链表中//输出顺序等于添加顺序singlelinkedlist1.add(hero1);singlelinkedlist1.add(hero3);//hero3与hero2打乱了顺序singlelinkedlist1.add(hero2);//hero3与hero2打乱了顺序singlelinkedlist1.add(hero4);singlelinkedlist1.add(hero5);//4.将创建好的节点加入到创建好的链表中//输出顺序按照编号大小,而不是加入顺序/*singlelinkedlist2.addByOrder(hero1);singlelinkedlist2.addByOrder(hero3);//hero3与hero2打乱了顺序singlelinkedlist2.addByOrder(hero2);//hero3与hero2打乱了顺序singlelinkedlist2.addByOrder(hero5);//hero4与hero5打乱了顺序singlelinkedlist2.addByOrder(hero4);//hero4与hero5打乱了顺序singlelinkedlist2.addByOrder(hero4);//hero4已经存在,提示加不进去*///5.修改节点/*System.out.println("修改之前的链表:");singlelinkedlist1.list();HeroNode hero6 = new HeroNode(3, "小吴", "智多星~~");singlelinkedlist1.updata(hero6);System.out.println("修改之后的链表:");singlelinkedlist1.list();*///6.显示链表//singlelinkedlist1.list();//singlelinkedlist2.list();//7.删除节点,根据排名/*Scanner scanner = new Scanner(System.in);System.out.println("删除节点之前的链表:");singlelinkedlist1.list();System.out.println("输入要删除的英雄排名:");singlelinkedlist1.del(scanner.nextInt());System.out.println("删除节点之后的链表:");singlelinkedlist1.list();*///8.计算单链表的有效节点个数/*singlelinkedlist1.list();System.out.println("单链表的有效节点个数为:" + singlelinkedlist1.getLength(singlelinkedlist1.getHead()));singlelinkedlist1.del(1);singlelinkedlist1.list();System.out.println("单链表的有效节点个数为:" + singlelinkedlist1.getLength(singlelinkedlist1.getHead()));*///9.找单链表中的倒数第k个节点singlelinkedlist1.list();HeroNode res = singlelinkedlist1.findLastIndexNode(singlelinkedlist1.getHead(), 2);System.out.println("res = " + res);}
}//一、定义 SingleLinkedList 类,管理梁山好汉
class SingleLinkedList{//先初始化一个节点头,头节点不要动,其数据域不存放具体的数据private HeroNode head = new HeroNode(0, "", "");//获得链表头节点的方法public HeroNode getHead() {return head;}//1.添加节点到单向链表,输出顺序等于添加顺序//思路:不考虑编号时,直接把新节点添加到当前链表的末尾//(1)找到当前链表的最后节点//(2)将最后节点的 next 指向新的节点public void add(HeroNode heroNode) {//因为head节点不能动,因为需要一个辅助节点 tempHeroNode temp = head;//<1>遍历链表,找到最后一个节点while(true) {//对于不清楚具体循环次数的遍历,要用while循环//找到链表的最后一个节点if(temp.next == null) {//若找到链表最后一个节点break;//跳出循环}//如果没有找到最后一个节点,则将 temp 后移temp = temp.next;}//<2>当退出while循环时, temp 就指向了链表的最后一个节点//将最后这个节点的 next 指向新的节点temp.next = heroNode;}//2.添加节点到单向链表,输出顺序等于编号顺序,而不是加入顺序//入错链表中已经存在待添加的编号,则添加失败public void addByOrder(HeroNode heroNode) {//因为头节点不能动,因为需要一个辅助节点(指针)来帮助找到添加的位置//因为是单链表,因此需要找到的 temp 是待添加节点的前一个位置,否则加入不了HeroNode temp = head;boolean flag = false;//flag 表示添加的编号是否存在,默认为false,表示不存在//(1)开始遍历while(true) {//目的是找到插入的位置if(temp.next == null) {//说明 temp 已经在链表的最后break;}if(temp.next.no > heroNode.no) {//找到插入位置,就在 temp 的后面插入break;}else if(temp.next.no == heroNode.no) {//说明希望添加的 heroNode 的编号已经存在flag = true;//说明编号已经存在break;}//若上面的情况都没有出现,则将 temp 往后移,继续遍历链表temp = temp.next;}//退出 while 循环//(2)判断 flag 的值if(flag) {//若 flag 为 true ,说明待插入的英雄编号已经存在,不能插入System.out.printf("待插入的英雄(排名 = %d)不存在!\n", heroNode.no);}else {//可以插入,插入到 temp 与 temp.next 之间heroNode.next = temp.next;temp.next = heroNode;}}//3.显示链表public void list() {//(1)先判断链表是否为空if(head.next == null) {System.out.println("链表为空");return;//结束方法,并不返回数值}//(2)链表非空,输出链表//因为头节点不能动,因此需要一个辅助变量来遍历链表HeroNode temp = head.next;while(true) {//<1>判断是否到链表最后//if的判断条件不能用 temp.next == null ,因为这会导致最后一个节点无法输出//如果 temp == null ,就表示 temp 的上一个节点就是链表的最后一个节点,且上一个节点的地址域就等于 temp //temp是一个引用变量,其本质是对象的地址if(temp == null) {break;//已经遍历完链表}//<2>没有到链表最后,输出节点的信息System.out.println(temp);//将temp后移,一定要记得这个操作temp = temp.next;}}//4.修改节点的信息,根据节点的 no 来修改,即不能修改 no ,只能修改 name 和 nickname//根据 newHeroNode 的 no 来修改即可public void updata(HeroNode newHeroNode) {//(1)先判断链表是否为空if(head.next == null) {System.out.println("链表为空!");return;//结束方法,一定不能丢掉!}//(2)链表非空,找到需要修改的节点,根据排名 no 来修改内容//惯例,先定义一个辅助变量HeroNode temp = head.next;boolean flag = false;//表示是否找到该节点,默认为 false ,没有找到//<1> 判断有没有找到排名 nowhile(true) {if(temp == null) {//已经遍历完链表break;//跳出循环}if(temp.no == newHeroNode.no) {//找到了flag = true;//找到了break;//跳出循环}temp = temp.next;//没有找到,继续遍历}//结束循环//<2> 根据 flag 判断是否找到要修改的节点if(flag) {//找到了temp.name = newHeroNode.name;temp.nickname = newHeroNode.nickname;}else {//没有找到System.out.printf("没有找到排名为%d的英雄\n", newHeroNode.no);}}//5.删除某一个节点,根据排名//思路//1. 按照惯例, head 不能动,因此需要一个辅助节点找到待删除节点的前一个节点//2. 在比较时,用 temp.next.no 与  待删除节点.no 来比较public void del(int no) {HeroNode temp = head;boolean flag = false;//标志是否找到待删除的节点,默认没找到,为 false//(1) 遍历链表,找到待删除的节点的前一个节点while(true) {if(temp.next == null) {//已经到达链表最后break;}if(temp.next.no == no) {//找到待删除的节点的前一个节点flag = true;break;}temp = temp.next;//没有找到待删除节点的前一个节点,继续遍历链表}//(2) 根据 flag 的值来判断是否找到待删除节点的前一个节点if(flag) {//找到了temp.next = temp.next.next;}else {System.out.printf("要删除的%d节点不存在!", no);}}//6.求单链表中有效节点的个数(若带头节点,则不统计头节点)/*** @param head 是头节点* @return 返回有效节点的个数*/public static int getLength(HeroNode head) {//1.首先判断链表是否为空,为空则返回0if(head.next == null) {return 0;}//2.单链表非空int length = 0;//定义一个辅助变量,不统计头节点HeroNode cur = head.next;while(cur != null) {length++;cur = cur.next;//cur后移,继续遍历}return length;}//7.找到链表中的倒数第K个节点//思路//1. 编写一个方法,接收 head 节点和 index(表示倒数第 index 个节点)//2. index表示是倒数第 index 个节点//3. 先把链表从头到尾遍历,得到链表的总长度size(直接调用 getLength 方法)//4. 得到 size 后,从链表的第一个开始遍历(size - index)个,就找到了倒数第 index 个节点//5. 如果找到了,则返回该节点,否则返回 nullpublic static HeroNode findLastIndexNode(HeroNode head, int index) {//1.先判断链表是否为空if(head.next == null) {return null;//没有找到}//2.第一次遍历整个单链表得到链表的长度(有效节点个数),直接调用 getLength 方法int size = getLength(head);//3.第二次遍历 (size - index)个节点,找到倒数第 index 节点并将其返回//(1)先做一个 index 的校验,因为不存在倒数第0个、第-1个、倒数第6个(加入链表长度为5)节点if(index <= 0 || index > size) {//越界return null;}//(2)定义一个辅助节点 cur ,用 for 循环定位到倒数第 index 个节点HeroNode cur = head.next;for(int i = 0; i < size - index; i++) {cur = cur.next;}return cur;}
}//二、定义 HeroNode,每个 HeroNode 对象代表一个节点
class HeroNode{public int no;//排名public String name;//名字public String nickname;//昵称public HeroNode next;//指向下一个节点//1.创建HeroNode对象的构造器public HeroNode(int no, String name, String nickname) {this.no = no;this.name = name;this.nickname = nickname;}//2.为了显示方便,重写toString方法@Overridepublic String toString() {return "HeroNode [排名 = " + no + ", 姓名 = " + name + ", 绰号 = " + nickname + "]";}
}
二、结果1(依次是倒数第2、第1、第6、第0、第-1个节点)
开始测试... ... ... ... ...(倒数第2个节点)
HeroNode [排名 = 1, 姓名 = 宋江, 绰号 = 及时雨]
HeroNode [排名 = 3, 姓名 = 吴用, 绰号 = 智多星]
HeroNode [排名 = 2, 姓名 = 卢俊义, 绰号 = 玉麒麟]
HeroNode [排名 = 4, 姓名 = 公孙胜, 绰号 = 入云龙]
HeroNode [排名 = 5, 姓名 = 关胜, 绰号 = 大刀]
res = HeroNode [排名 = 4, 姓名 = 公孙胜, 绰号 = 入云龙]开始测试... ... ... ... ...(倒数第1个节点)
HeroNode [排名 = 1, 姓名 = 宋江, 绰号 = 及时雨]
HeroNode [排名 = 3, 姓名 = 吴用, 绰号 = 智多星]
HeroNode [排名 = 2, 姓名 = 卢俊义, 绰号 = 玉麒麟]
HeroNode [排名 = 4, 姓名 = 公孙胜, 绰号 = 入云龙]
HeroNode [排名 = 5, 姓名 = 关胜, 绰号 = 大刀]
res = HeroNode [排名 = 5, 姓名 = 关胜, 绰号 = 大刀]开始测试... ... ... ... ...(倒数第6个节点)
HeroNode [排名 = 1, 姓名 = 宋江, 绰号 = 及时雨]
HeroNode [排名 = 3, 姓名 = 吴用, 绰号 = 智多星]
HeroNode [排名 = 2, 姓名 = 卢俊义, 绰号 = 玉麒麟]
HeroNode [排名 = 4, 姓名 = 公孙胜, 绰号 = 入云龙]
HeroNode [排名 = 5, 姓名 = 关胜, 绰号 = 大刀]
res = null开始测试... ... ... ... ...(倒数第0个节点)
HeroNode [排名 = 1, 姓名 = 宋江, 绰号 = 及时雨]
HeroNode [排名 = 3, 姓名 = 吴用, 绰号 = 智多星]
HeroNode [排名 = 2, 姓名 = 卢俊义, 绰号 = 玉麒麟]
HeroNode [排名 = 4, 姓名 = 公孙胜, 绰号 = 入云龙]
HeroNode [排名 = 5, 姓名 = 关胜, 绰号 = 大刀]
res = null开始测试... ... ... ... ...(倒数第-1个节点)
HeroNode [排名 = 1, 姓名 = 宋江, 绰号 = 及时雨]
HeroNode [排名 = 3, 姓名 = 吴用, 绰号 = 智多星]
HeroNode [排名 = 2, 姓名 = 卢俊义, 绰号 = 玉麒麟]
HeroNode [排名 = 4, 姓名 = 公孙胜, 绰号 = 入云龙]
HeroNode [排名 = 5, 姓名 = 关胜, 绰号 = 大刀]
res = null
代码2(LeetCode中有这个题目)
/*** 找到链表的倒数第 k 个节点,将头节点当成链表的首节点*/
public class MyTest {public static void main(String[] args) {//创建若干个节点ListNode listnode1 = new ListNode(2);ListNode listnode2 = new ListNode(3);ListNode listnode3 = new ListNode(4);ListNode listnode4 = new ListNode(5);//创建链表,加入节点LinkedList linkedlist = new LinkedList();linkedlist.addListNode(listnode1);linkedlist.addListNode(listnode2);linkedlist.addListNode(listnode3);linkedlist.addListNode(listnode4);//显示链表linkedlist.list(linkedlist.getHead());//找到倒数第 k 个节点System.out.println("------------------------------");ListNode kth = linkedlist.findKthNode(linkedlist.getHead(), 2);linkedlist.list(kth);}
}class ListNode{public int val;public ListNode next;// ListNode 类的构造方法public ListNode(int val) {this.val = val;}//为了显示方便,重写 toString 方法@Overridepublic String toString() {return "" + val;}
}class LinkedList{//初始化一个头节点private ListNode head = new ListNode(1);//获得链表头节点的方法public ListNode getHead() {return head;}//添加节点到单链表的方法public void addListNode(ListNode listnode) {//由于头节点不能动,所以需要一个赋值节点 tempListNode temp = head;//遍历单链表,找到最后一个节点while(true) {//如果找到单链表的最后一个节点if(temp.next == null) {temp.next = listnode;break;}//没有找到单链表最后一节点,则继续遍历temp = temp.next;}}//找到单链表倒数第 K 个节点的方法public ListNode findKthNode(ListNode head, int k) {//1.先判断链表是否为空if(head == null) {return null;}//2.链表不为空,遍历整个链表,确定链表长度int length = 0;ListNode temp = head; while(temp != null) {length++;temp = temp.next;}//3.遍历链表,找到倒数第 k 个节点//(1)先对 k 进行校验,此步骤体现程序的鲁棒性,不能忽略!!!if(k <= 0 || k > length) {return null;}//(2)k 值符合要求,新建一个辅助节点ListNode cur = head;for(int i = 0; i < length - k; i++) {cur = cur.next;}return cur;}//打印输出链表public void list(ListNode head){//首先判断链表是否为空if(head == null) {//把头节点当成链表的首节点System.out.println(head);return;}//链表非空,打印输出ListNode temp = head;System.out.print("[");while(true) {//判断是否到链表最后if(temp.next == null) {//到达链表最后System.out.print(temp);break;//退出循环}//没有到链表最后,继续打印输出if(temp.next != null) {System.out.print(temp + ",");}//将 temp 后移temp = temp.next;}System.out.println("]");}
}
二、结果1(依次是倒数第2、第1、第6、第0、第-1个节点)
[1,2,3,4,5]
------------------------------
[4,5][1,2,3,4,5]
------------------------------
[5][1,2,3,4,5]
------------------------------
null[1,2,3,4,5]
------------------------------
null[1,2,3,4,5]
------------------------------
null

Java数据结构与算法———(10)单链表应用实例,找到单链表中倒数第K个节点相关推荐

  1. Java 算法之 “删除链表中倒数第k个节点”【钢镚核恒】

    删除链表中倒数第k个节点 简介 题目描述:给定⼀个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点[Leetcode] 链表中倒数第k个节点 , 和这篇文章使用的方法一致,就是变成找到倒数k+ ...

  2. 递增的整数序列链表的插入_每日算法题 | 剑指offer 链表专题 (5)链表中倒数第k个节点...

    点击上方"Jerry的算法和NLP",选择"星标"公众号 重磅干货,第一时间送达 题目 链表中倒数第k个节点 题目要求 输入一个链表的头结点,从尾到头反过来打印 ...

  3. python 链表倒数第k个节点_链表-删除单链表中倒数第k个节点

    题目 实现一个函数,一个可以删除单链表中倒数第k个节点 难度 简单 分析 本题比较简单,实现方法多种多样,这里提供一种方法 首先明确一点,在单链表中删除倒数第k个节点,需要找到他的前一个节点,让前一个 ...

  4. [数据结构]题海啊,全是水(三)链表中倒数第k个节点、链表的回文结构、链表分割

    这是一个目录 链表中倒数第k个节点 解法一 解法二 链表的回文结构 思路 代码 链表分割 思路 代码 最后 菜鸡大学生的数据结构--刷题篇3 我们的第三题小宝贝儿回归了! 菜鸡大学生明白,笔试oj题目 ...

  5. 【剑指offer - C++/Java】14、链表中倒数第k的节点

    在线题目链接:链表中倒数第k的节点 文章目录 1 题目描述 2 题目分析 2.1 Java代码 2.2 C++代码 3 总结 1 题目描述 输入一个链表,输出该链表中倒数第k个结点. 2 题目分析 这 ...

  6. 力扣—— 19. 删除链表的倒数第 N 个结点(java)、剑指 Offer 22. 链表中倒数第k个节点(java)

    19. 删除链表的倒数第 N 个结点(java) 一.题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. 进阶:你能尝试使用一趟扫描实现吗? 输入:head = [1,2,3 ...

  7. 《漫画算法2》源码整理-8 链表中倒数第K个节点元素

    链表中倒数第K个节点元素 public class KthFromEnd {public static Node findKthFromEnd(Node head, int k){Node p1 = ...

  8. 【剑指offer】面试题22:链表中倒数第k个节点(Java)

    输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点.例如,一个链表有6个节点,从头节点开始,它们的值依次是1.2.3.4.5.6.这个链 ...

  9. 【算法】剑指 Offer 22. 链表中倒数第k个节点

    1.概述 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点. 例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1.2.3. ...

  10. leetcode 剑指 Offer 22. 链表中倒数第k个节点

    题目描述: 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点. 例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1.2.3 ...

最新文章

  1. 网路游侠:某软件版WEB应用防火墙试用
  2. inbox status and ServiceOrder Status
  3. 4. 用MVC实现URL路由
  4. 53 SD配置-定价配置-定义条件排斥组
  5. iphone7无服务_iphone7无服务无信号怎么办
  6. 2021-05-06 git 设置XX门8580端口代理访问github
  7. (tip_修订0618)bmp 32位转24位
  8. 15天玩转redis —— 第四篇 哈希对象类型
  9. 匹夫细说C#:从园友留言到动手实现C#虚函数机制
  10. 【硬刚大数据之面试篇】2021年从零到大数据专家面试篇之ClickHouse篇
  11. 计算机组成原理——总线标准
  12. 修改linux服务器密码
  13. STM32 DCMI OV9655 直接在LCD显示
  14. WorldView卫星遥感影像数据/米级分辨率遥感影像
  15. Win XP系统无法关机时如何强制软关机
  16. Android 一分钟快速使用极光推送
  17. 全解MySQL之架构篇:自顶向下深入剖析MySQL整体架构
  18. android 斜边_Android -- 一个滑动旋转的弧形菜单
  19. Apriori算法总结
  20. neon浮点运算_NEON简单介绍

热门文章

  1. SEO搜索引擎优化教程-传智-专题视频课程
  2. 一款专为升压、升降压开关电源设计的专用DC-DC 控制器芯片 OC6801B
  3. 一个比尔盖茨都怕的人?他是谁?
  4. 3.3栈和队列的应用
  5. C#替换DataTable列名
  6. 电脑软件卡住,调不出任务管理器
  7. Struts2访问验证码异常解决OgnlValueStack:64 - ..java.lang.NumberFormatException: For input string: 1494056190
  8. 鹰志------------摘自《散文》
  9. Win7下安装SVN服务端
  10. LaTex 连字符多篇连续引用