此文章仅作为自己学习过程中的记录和总结,同时会有意地去用英文来做笔记,一些术语的英译不太准确,内容如有错漏也请多指教,谢谢!


一、概述

  1. 获取单链表的有效元素个数【新浪面试题1】
  2. 获取单链表倒数第k个结点【新浪面试题2】
  3. 反转单链表【腾讯面试题】
  4. 从尾到头打印单链表【百度面试题】
  5. 合并两个有序的单链表,合并之后的链表依然有序

此文章会根据以上五个问题分别给出实现代码,以及一些注意事项。在文末会给出检测代码。

(关于属性、构造器、结点结构及基本方法,具体可见:数据结构与算法–单链表(Single Linked List))


二、获取单链表的有效元素个数

此题难度不高,没有多少笔记。

    /*** Get the length of the list.* 获取单链表的有效长度【新浪面试题1】** @return The amount of the effective nodes*/public int getLength() {HeroNode temp = head.next;int count = 0;while (temp != null) {count++;temp = temp.next;}return count;}

三、获取单链表倒数第k个结点

关于这个问题,有很多解决的方法,此处我只就其中两个方法做笔记。

  1. 蛮力算法(不推荐);
  2. 通过两个相隔k距离的“指针”一起移动来找到目标结点(更优解)
  • -方法①:蛮力算法
    首先,通过getLength()方法获取单链表的长度。
    之后,通过 (getLength()-k) 的循环,来找到目标结点。
    /*** Find the No.k penultimate node in a single linked list.* 查找单链表中的倒数第k个结点【新浪面试题2】* <p>* 方法:蛮力算法。* 首先,通过getLength()方法获取单链表的长度。* 之后,通过getLength()-k的循环,来找到目标结点。** @return The No.k penultimate node in a single linked list*/public HeroNode findLastIndexNode(int index) {if (head.next == null) {System.out.println("The list is empty, cannot find node...");return null;}/* Method : brutal force algorithm.First, get the length of the list. Judge if it's valid.Then, loop again to find the target node. */int length = getLength();if (index > length || index <= 0) { // Check if the index given is valid or not.throw new RuntimeException("The given index is illegal (bigger than length / smaller than 1)...");}HeroNode temp = head.next;for (int i = 0; i < length - index; i++) {temp = temp.next;}return temp;}

该方法的缺点:效率相对较低,由于getLength()方法需要遍历单链表,之后又要再一次循环去找到目标结点,因此此方法需要两次遍历(循环)。

  • -方法②:通过两个相隔k距离的“指针”一起移动来找到目标结点
    首先,让第一个“指针”移动k距离,再让二者一起移动。
    之后,当第一个“指针”到达单链表末尾时(通过辅助计数器判断),第二个“指针”所指即为目标结点。
   /*** Find the No.k penultimate node in a single linked list.* 查找单链表中的倒数第k个结点【新浪面试题2】* <p>* 方法:通过两个相隔k距离的“指针”一起移动来找到目标结点。(更优解)* 首先,让第一个“指针”移动k距离,再让二者一起移动。* 之后,当第一个“指针”到达单链表末尾时(通过辅助计数器判断),第二个“指针”所指即为目标结点。** @return The No.k penultimate node in a single linked list*/public HeroNode findLastIndexNode(int index) {if (head.next == null) {System.out.println("The list is empty, cannot find node...");return null;}/* Method : use two indicators that have the interval of "k".First, let one of the indicator moves "k".Then, let the two indicators move together.When the first one gets to the end of the list,The second indicator is now pointing to the target node.运用两个相隔k的“指针”来找到目标结点。*/HeroNode first = head.next;HeroNode second = head.next;int count = 0;while (first != null) {count++;if (count > index) {// Already has an interval of "k" between the two indicators,// they can move together.// 此时两个“指针”已经相隔k,一起移动。second = second.next;}first = first.next;}if (index > count) { // If the given index is invalid.throw new RuntimeException("The given index is illegal (bigger than length / smaller than 1)...");}return second;}

相比之下,第二种方法只需要一次遍历,效率更高。


四、反转单链表

此题较难,需要多琢磨。

-方法:遍历原链表,每遍历一个结点,就将其取出,并放在新的链表reverseHead的最前端,此过程相当于使用头插法创建新的单链表。(注意:辅助变量的使用)

 /*** Reverse the single linked list.* 将单链表反转【腾讯面试题】* <p>* 方法:遍历原链表,每遍历一个结点,就将其取出,* 并放在新的链表reverseHead的最前端(头插法)。* (注意:辅助变量的使用)*/public void reverseList() {if (head.next == null || head.next.next == null) {return;}HeroNode reverseHead = new HeroNode(0, "", "");HeroNode cur = head.next;HeroNode next = null;while (cur != null) {next = cur.next;cur.next = reverseHead.next;reverseHead.next = cur;cur = next;}head.next = reverseHead.next;}

五、从尾到头打印单链表

-方法

  1. 采用递归方法(不推荐,效率低)
  2. 先将单链表反转,再遍历打印(不推荐,因为会破坏原链表结构,需要复原,效率低)
  3. 利用栈(stack),遍历时将各个结点压入栈中。之后再次遍历,将各个结点逐个出栈(推荐)(虽然遍历两次,但时间复杂度为2n,可看作O(n))

此处只记录方法③的代码实现。

   /*** Print the nodes in the list reversely.* 从尾到头打印单链表【百度面试题】* <p>* 方法①:采用递归方法。(不推荐,效率低)* <p>* 方法②:先将单链表反转,再遍历打印。(不推荐,因为会破坏原链表结构,需要复原,效率低)* <p>* 方法③:利用栈(stack),遍历时将各个结点压入栈中。之后再次遍历,将各个结点逐个出栈。(推荐)* (虽然遍历两次,但时间复杂度为2n,可看作O(n))*/public void reverseShow() {if (head.next == null) {System.out.println("The list is empty...");return;}HeroNode temp = head.next;Stack<HeroNode> heroNodeStack = new Stack<>();// Push the nodes into the stack.while (temp != null) {heroNodeStack.push(temp);temp = temp.next;}// Pop the nodes from the stack.while (!heroNodeStack.empty()) { // Or "heroNodeStack.size() > 0"System.out.println(heroNodeStack.pop());}}

此处的出栈条件可以是:

  1. !(heroNodeStack.empty())
  2. heroNodeStack.size() > 0

六、合并两个有序的单链表,使合并后的链表依然有序

-方法:
通过两个“指针”分别指示两个链表的当前位置。每次比较二者所指向元素的大小,根据所需顺序打印。

特别注意此题中辅助变量的使用。
(此例中,我通过结点的属性“Name”来排序)

  /*** Merge two single linked lists(having been ordered) by order.* 合并两个有序的单链表,合并之后的链表依然有序* <p>* 方法:通过两个“指针”分别指示两个链表的当前位置。每次比较二者所指向元素的大小,* 根据所需顺序打印。*/public void mergeList(SingleLinkedList anotherList) {if (head.next == null || anotherList.head.next == null) {System.out.println("One of the lists is empty, cannot merge...");return;}// 指示单链表1上当前所判断到的结点HeroNode temp1 = head.next;// 指示单链表2上当前所判断到的结点HeroNode temp2 = anotherList.head.next;// 指示最近一个判断要加入合并链表的结点HeroNode cur = null;// 指示cur的下一个结点,起辅助作用,为了使得合并之后仍能继续遍历单链表HeroNode next = null;// 合并链表的头结点HeroNode mergedHead = new HeroNode(0, "", "");// 先让合并链表的头指针指向符合条件的结点if (temp1.getName().compareToIgnoreCase(temp2.getName()) <= 0) {mergedHead.next = temp1;cur = temp1;temp1 = temp1.next;} else {mergedHead.next = temp2;cur = temp2;temp2 = temp2.next;}// 逐个判断并插入合并链表while ((temp1 != null) && (temp2 != null)) {if (temp1.getName().compareToIgnoreCase(temp2.getName()) <= 0) {next = temp1.next; // 将即将被合并的结点的下一个结点存储起来cur.next = temp1; // 让合并链表的最后一个结点指向即将被合并的结点cur = temp1; // 此时已经合并,让被合并的结点成为合并链表的最后一个结点temp1 = next; // 存储起来的结点成为单链表1上当前所被判断到的结点} else {next = temp2.next;cur.next = temp2;cur = temp2;temp2 = next;}}// 当单链表2已经遍历结束,只需要将单链表1剩余的结点插入到合并链表while (temp1 != null) {next = temp1.next;cur.next = temp1;cur = temp1;temp1 = next;}// 当单链表1已经遍历结束,只需要将单链表2剩余的结点插入到合并链表while (temp2 != null) {next = temp2.next;cur.next = temp2;cur = temp2;temp2 = next;}head = mergedHead;}

七、测试代码

/*SingleLinkedListDemoZzay2021/01/18*/
package com.zzay.linkedlist.demo;import com.zzay.linkedlist.impl.HeroNode;
import com.zzay.linkedlist.impl.SingleLinkedList;/*** CONTENTS:* (1) Get the length of the single linked list. 获取单链表有效结点个数【新浪面试题1】* (2) Find the No.k penultimate node in a single linked list. 获取单链表倒数第k个结点【新浪面试题2】* (3) Reverse the single linked list. 反转单链表【腾讯面试题】* (4) Print the nodes in the list reversely. 从尾到头打印单链表【百度面试题】* (5) Merge two single linked lists(having been ordered) by order. 合并两个有序的单链表,合并之后的链表依然有序* * @author Zzay* @version 2021/01/18*/
public class SingleLinkedListDemo {public static void main(String[] args) {SingleLinkedList singleLinkedList = new SingleLinkedList();/* Add nodes into the single linked list by order (ascending). */singleLinkedList.addByOrder(new HeroNode(1, "Jay", "Yellow Chocolate"));singleLinkedList.addByOrder(new HeroNode(4, "Paul Pierce", "Truth"));singleLinkedList.addByOrder(new HeroNode(2, "Kobe Bryant", "Black Mamba"));singleLinkedList.addByOrder(new HeroNode(3, "Dirk Nowitzki", "German Race Car"));/* Show the contents of the single linked list. */singleLinkedList.show();/* Get the length of the single linked list.获取单链表的有效元素个数【新浪面试题1】 */System.out.println("The length of the linked list is: " + singleLinkedList.getLength());/* Find the No.k penultimate node in a single linked list.获取单链表倒数第k个结点【新浪面试题2】 */try {System.out.println(singleLinkedList.findLastIndexNode(3)); // Valid
//            System.out.println(singleLinkedList.findLastIndexNode(5)); // Out of range(bigger).
//            System.out.println(singleLinkedList.findLastIndexNode(0)); // Out of range(smaller)System.out.println();} catch (RuntimeException e) {System.out.println(e.getMessage());}/* Reverse the single linked list.反转单链表【腾讯面试题】 */singleLinkedList.reverseList();System.out.println("Here's the reversed version of the list:");singleLinkedList.show();singleLinkedList.reverseList();System.out.println();/* Print the nodes in the list reversely.从尾到头打印单链表【百度面试题】 */System.out.println("Here we print the list reversely:");singleLinkedList.reverseShow();System.out.println();/* Merge two single linked lists(having been ordered) by order.合并两个有序的单链表,合并之后的链表依然有序 */SingleLinkedList anotherList = new SingleLinkedList();anotherList.addByOrder(new HeroNode(5, "Allen Iverson", "The Answer"));anotherList.addByOrder(new HeroNode(6, "Michael Jordan", "Air Jordan"));singleLinkedList.mergeList(anotherList);singleLinkedList.show();}
}

数据结构与算法--单链表相关面试题相关推荐

  1. 数据结构与算法——单链表、双向链表

    目录 ​编辑 特点: 一.单链表 1.增加数据到链表尾部 2.增加数据到链表指定位置 思路: 代码实现: 3.修改单链表数据 3.单链表数据删除 4.单链表相关面试题 二.双向链表 1.双向链表遍历 ...

  2. 韩老师——数据结构与算法—单链表的生成及增删改查操作和常见关于链表的面试题java代码实现

    话不多说直接上代码. public class SingleLinkedListDemo {public static void main(String[] args) {//测试HeroNode n ...

  3. 数据结构与算法-单链表的常见面试题(单链表的长度,单链表倒数第k个数据)

    单链表的长度,单链表倒数第k个数据 求单链表中节点的个数 思路分析 完整代码 查找单链表中倒数第k个节点 思路如下: 全量代码 求单链表中节点的个数 在上一节代码的基础上我们来学习 思路分析 我们创建 ...

  4. 头歌平台数据结构与算法 单链表实验 第1关:倒置链表

    任务描述 相关知识 实验目的 实验任务 实验说明 编程要求 测试说明 任务描述 本关任务:请在右侧编辑器的注释行填入适当内容来完成算法,以实现指定的功能,并通过运行来验证. 相关知识 实验目的 理解线 ...

  5. [数据结构与算法] 单链表的简单demo

    Vc6之下编译通过.. 1 /******************************************************* 2 * @: Project: 单链表数据结构演示 3 * ...

  6. 常考数据结构与算法:单链表的排序

    题目描述 给定一个无序单链表,实现单链表的排序(按升序排序). 输入 [1,3,2,4,5] 返回值 {1,2,3,4,5} public class SortInListME {public sta ...

  7. 线性表之链式存储结构_单链表相关算法

    在存储结构上,不需要连续的存储空间,需要上一个结点的指针域 指向下一个结点即可,找到一个结点就可以找到下一个结点. 学习教材是大话数据结构,加上自己的一些个人理解.这个算法 有点绕,需要对指针 相关内 ...

  8. python定义链表节点_Python数据结构与算法之链表定义与用法实例详解【单链表、循环链表】...

    本文实例讲述了Python数据结构与算法之链表定义与用法.分享给大家供大家参考,具体如下: 本文将为大家讲解: (1)从链表节点的定义开始,以类的方式,面向对象的思想进行链表的设计 (2)链表类插入和 ...

  9. 单链表的面试题——Java数据结构

    单链表的面试题--Java数据结构 说明 本篇博客介绍的是Java数据结构中的单链表,以及一点栈的知识,主要进行代码演示面试中对单链表这一部分的工作要求. 本文介绍顺序如下: (1)什么是单链表,以及 ...

最新文章

  1. 面试现场:遇到不会回答的问题,如何力挽狂澜 ?
  2. python中常见的流程结构-python常见对象的结构
  3. 安装pr_PR 一键转场插件 安装教程
  4. activity-alias的使用
  5. linux 复用寄存器,I/O多路复用一些概念
  6. canvas 在其他画好的上面继续画_详解canvas绘制多张图的排列顺序问题
  7. Java多线程基础总结
  8. 解线性方程组的迭代法(雅可比、高斯-塞德尔迭代法)
  9. 2019牛客多校第三场F Planting Trees(单调队列)题解
  10. hadoop1.X安装
  11. 会展管理系统是计算机软件系统,展商管理系统|会展管理信息系统
  12. 【软硬链接总结】描述linux下软链接和硬链接的区别(面试题)
  13. C语言--第一周作业(更改)
  14. 最长公共子序列的问题
  15. 实战 Vue 之生命周期钩子函数执行顺序
  16. 为什么都在选择学习Java
  17. OpenGL进阶示例1——动态画线(虚线、实线、颜色、速度等)
  18. 使用vagrant搭建三台虚拟机环境
  19. 如何宣传Android作为Bluetooth LE外围设备
  20. PPM、PCM和PWM的区别, I2S与pcm的区别

热门文章

  1. asp.net928-研究生报名系统
  2. 装系统时无法创建新的分区
  3. python中常见的三种选择结构_在Python中,实现多分支选择结构的最佳方法是
  4. 关于数据治理的读书笔记 - 什么是组织机制?
  5. NaiveBayes
  6. secureCRT串口传送文件
  7. 如何用快启动pe修复win10系统引导? 神器
  8. 对于计算机专业的个人理解
  9. 存储引擎,表的数据类型
  10. JAVA高并发多线程必须懂的50个问题