Java 八道经典面试题之链表题

Java 八道经典面试题之链表题

什么是链表?

链表是一种常见的线性数据结构,与数组最大的区别是:链表的元素在物理空间上不是连续的,而是靠指针相连。链表由一连串的结点组成,每个结点都包含两部分内容,一部分是存储数据的数据域,另一部分是存储下一个结点地址的指针域,也可以包含前一个结点的地址指针域(双向链表)。

单链表 & 双向链表

单链表是每个结点只指向它的后继结点,没有指向前一个结点的指针。常见的有单向链表、循环单向链表、静态链表。双向链表是每个结点既有指向后继结点的指针,也有指向前驱结点的指针,和单向链表相比,双向链表可以从任意一个结点开始往前或往后遍历。

链表的操作

链表的基本操作包括:插入、删除、遍历。

链表的插入操作通常有三种:在链表头部插入结点、在链表尾部插入结点、在链表中间插入结点。

链表的删除操作通常有两种:删除链表中指定结点、按照位置删除链表的结点。

遍历链表的方法主要有两种:通过循环遍历链表,递归方式遍历链表。

经典面试题:反转链表

题目描述

输入一个链表的头结点,反转该链表并输出反转后链表的头结点。

分析步骤

  1. 定义三个指针:当前结点指针,前驱结点指针,后继结点指针;
  2. 遍历链表,不断更新指针,变换指针方向,实现链表反转;
  3. 时间复杂度 O(n),空间复杂度 O(1)。

代码示例

public ListNode reverseList(ListNode head) {
    ListNode pre = null;
    ListNode cur = head;
    while (cur != null) {
        ListNode next = cur.next;  //保存下一个结点
        cur.next = pre;  //反转指针
        pre = cur;  //更新前驱结点指针
        cur = next;  //更新当前结点指针
    }
    return pre;  //返回反转后的头结点指针
}

示例说明

以链表 1->2->3->4->5 为例,反转后的链表应该为 5->4->3->2->1。

我们设置三个指针:precurnext,分别指向前驱结点、当前结点和后继结点。在遍历链表的过程中,不断修改这三个指针的指向,即可实现链表的反转。最后返回 pre 即可。

如下所示,指针的变化顺序为:1->2->3->4->5,变为 5->4->3->2->1。

初始化:
pre = null;
cur = 1 -> 2 -> 3 -> 4 -> 5;
next = null;

第一次遍历:
next = cur.next = 2 -> 3 -> 4 -> 5;
cur.next = pre = null;
pre = cur = 1 -> null;
cur = next = 2 -> 3 -> 4 -> 5;

第二次遍历:
next = cur.next = 3 -> 4 -> 5;
cur.next = pre = 1 -> null;
pre = cur = 2 -> 1 -> null;
cur = next = 3 -> 4 -> 5;

第三次遍历:
next = cur.next = 4 -> 5;
cur.next = pre = 2 -> 1 -> null;
pre = cur = 3 -> 2 -> 1 -> null;
cur = next = 4 -> 5;

第四次遍历:
next = cur.next = 5 -> null;
cur.next = pre = 3 -> 2 -> 1 -> null;
pre = cur = 4 -> 3 -> 2 -> 1 -> null;
cur = next = null;

返回结果:pre = 5 -> 4 -> 3 -> 2 -> 1 -> null;

经典面试题:链表中倒数第k个结点

题目描述

输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。

分析步骤

  1. 双指针法:定义两个指针 p1、p2,让 p1 先走 k-1 步,然后再同时移动 p1 和 p2,当 p1 到达链表尾时,p2 指向的即是链表中倒数第 k 个结点;
  2. 先遍历链表获取链表长度 n,然后从头开始遍历到第 n-k+1 个结点即可;
  3. 时间复杂度 O(n),空间复杂度 O(1)。

代码示例

public ListNode findKthToTail(ListNode head, int k) {
    ListNode p1 = head;
    ListNode p2 = head;
    for (int i = 0; i < k; i++) {
        if (p1 == null) return null;  //特判 k 大于链表长度的情况
        p1 = p1.next;
    }
    while (p1 != null) {
        p1 = p1.next;
        p2 = p2.next;
    }
    return p2;
}

示例说明

以链表 1->2->3->4->5 为例,要求找到倒数第 2 个结点,即输出 4。

我们设置两个指针:p1p2,初始时均指向链表头结点。p1 先走 1 步,p2 保持不动;p1 再走 1 步,p2 也走一步,此时 p1 到达了第 3 个结点,p2 到达了第 2 个结点;以此类推,当 p1 走到链表结尾时,p2 指向的结点即为所求。

public ListNode findKthToTail(ListNode head, int k) {
    ListNode p1 = head;
    ListNode p2 = head;
    for (int i = 0; i < k-1; i++) {  //p1 先走 k-1 步
        if (p1 == null) return null;  //特判 k 大于链表长度的情况
        p1 = p1.next;
    }
    while (p1.next != null) {  //同时移动 p1 和 p2
        p1 = p1.next;
        p2 = p2.next;
    }
    return p2;
}

总结

针对链表题,首先要了解链表的基本操作,包括插入、删除、遍历;其次,掌握链表的特点与算法思想,常见的题目包括反转链表、链表中倒数第k个结点、删除链表中重复的结点等等。在实际应用中,还需要注意链表元素为空、链表只有一个元素、链表长度小于 k 等边界情况的处理,避免空指针错误等问题。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 八道经典面试题之链表题 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • C/C++中运算符的优先级、运算符的结合性详解

    C/C++中运算符的优先级、运算符的结合性详解 1. 运算符优先级 在C/C++中,不同的运算符具有不同的优先级。优先级高的运算符先于优先级低的运算符进行计算。下表列出了C/C++中常用运算符的优先级,优先级由高到低排列: 优先级 运算符 描述 1 () [] -> . 访问操作符 2 ++ — 后缀递增、递减 3 ++ — 前缀递增、递减 4 !…

    other 2023年6月28日
    00
  • win10临时文件夹移动到c盘根目录下怎么操作?临时文件夹移动到c盘教程

    下面是详细的操作攻略,我分别给出了Windows 10系统自带的方法和通过第三方软件进行操作的方法。 方法一:使用Windows自带的设置功能 打开“Windows设置”菜单,通过键盘快捷键 “Win+I” 实现 在“Windows设置”窗口中选择“系统”,然后选择“存储” 在“存储”菜单下方找到“更多存储设置”,点击进入 在更多存储设置页面下,找到“临时文…

    other 2023年6月27日
    00
  • Win10 Java jdk14.0.2安装及环境变量配置详细教程

    Win10 Java jdk14.0.2安装及环境变量配置详细教程 安装JDK 下载JDK 前往官网(https://www.oracle.com/java/technologies/javase-jdk14-downloads.html)下载JDK 14.0.2版本,并根据操作系统选择相应的安装包。 安装JDK 将下载的JDK安装包双击打开,跟随向导完成安…

    other 2023年6月27日
    00
  • win10电脑频繁蓝屏重启怎么解决?

    Win10电脑频繁蓝屏重启问题解决攻略 背景描述 频繁蓝屏重启是 Win10 电脑常见的一个问题。当电脑出现频繁蓝屏重启时,不仅会造成数据丢失,还会影响到我们的正常使用,因此需要我们及时解决这个问题。本文将会从多方面入手,详细讲解 Win10 电脑频繁蓝屏重启怎么解决。 解决方案 1. 更新系统补丁 Win10 系统经常会发布补丁来修复一些已知问题,因此我们…

    other 2023年6月27日
    00
  • element-ui 文件上传修改文件名的方法示例

    下面是关于element-ui文件上传修改文件名的方法示例的完整攻略: 1. element-ui文件上传基础知识 在使用element-ui进行文件上传时,需要先了解一些基础知识。element-ui提供了 el-upload 组件,可以用于文件上传。具体用法可以参考官方文档:el-upload 2. 修改上传文件的文件名 默认情况下,上传的文件的文件名是…

    other 2023年6月26日
    00
  • golang学习笔记—rand

    以下是详细讲解“golang学习笔记—rand”的完整攻略,过程中包含两个示例说明: golang学习笔记—rand 在Go语言中,rand包提供了伪随机数生成器,可以用于生成随机数。本攻略将介绍rand包的基本概念、函数和两个示例说明。 基本概念 在开始使用rand包之前,我们需要了解一些基本概念: 伪随机数:伪随数是一种看起来像随机数的数列,但是…

    other 2023年5月10日
    00
  • win7系统静态ip地址如何填写 win7系统静态ip填写方法图文详解

    Win7系统静态IP地址填写方法 在Win7系统中,如果需要设置静态IP地址,可以按照以下步骤进行操作: 打开控制面板:点击开始菜单,选择“控制面板”。 进入网络和共享中心:在控制面板中,选择“网络和 Internet”,然后点击“网络和共享中心”。 打开适配器设置:在网络和共享中心窗口中,点击左侧的“更改适配器设置”。 打开网络连接属性:在适配器设置窗口中…

    other 2023年7月30日
    00
  • 电脑右键新建菜单项太多怎么清理?

    当在电脑上右键点击鼠标时,弹出的“新建”菜单项可能会有很多选项,随着时间推移,这些选项可能会继续增加。这可能会让菜单变得混乱不堪,对于想要快速找到想要的选项的人来说,这可能非常困难。因此,清理右键新建菜单项成为了一种很有必要的方法。 以下是一些具体的步骤,可以帮助你清理电脑右键“新建”菜单项。 方法一:手动清理注册表 1.按下“Win + R”,打开运行窗口…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部