图解 LeetCode 算法汇总——链表

本文首发公众号:小码A梦

一般数据主要存储的形式主要有两种,一种是数组,一种是链表。数组是用来存储固定大小的同类型元素,存储在内存中是一片连续的空间。而链表就不同于数组。链表中的元素不是存储在内存中可以是不连续的空间

链表主要有两个元素:结点和指针。结点是存储数据,指针是指向下一个结点数据。

链表的有几个特点:

  • 不必按顺序存储数据,使用指针关联各个结点的数据。
  • 插入数据时间复杂度O(1)。
  • 单链表查询时间复杂度为O(n)。

JDK 链表源码

JDK 很多地方用到了链表,这里举例两个:HashMap 和 LinkedList。

HashMap

HashMap 基于数组 + 链表/红黑树的数据结构,其中链表用 Node 表示。主要存储数据和指向下一个结点的指针,源码如下所示。

//HashMap Node 部分源码
static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Node<K,V> next;Node(int hash, K key, V value, Node<K,V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}
}

以上蓝色的 Node 结点表示一个链表结点。

LinkedList

LinkedList 本身就是一个双链表,有前置指针和后置指针。

//LinkedList 部分源码
private static class Node<E> {E item;Node<E> next;Node<E> prev;Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
}

LeetCode 题解

LeetCode 有很多链表的题目,选取了几种比较典型的链表,面试的时候也经常会问到。

206.反转链表(简单)

题目描述

解法

链表结点不变,将指针方向反转。如果只是在一个链表的上操作,每次都需要遍历结点,比较繁琐。所以添加一个空链表 pre。pre 表示将指针向后,改成向前。比如 1 -> 2 变成 2 -> 1,先将 1 放在新的链表上,然后再将 2 放入新的链表,并指向 1。如下图所示:

总结一下解决步骤:

  • 设置一个空链表pre
  • 遍历链表,每次先将链表的next,赋值给一个新的链表。
  • 链表的next指向pre。
  • 当前链表赋值给pre。
  • 继续遍历next链表

整理好解题思路后,根据解题写出以下代码:

class Solution {public ListNode reverseList(ListNode head) {ListNode cur = head;ListNode pre = null;while(cur != null) {ListNode next = cur.next;cur.next = pre;pre = cur;cur = next; }return pre;}
}

19.删除链表的倒数第 N 个结点(中等)

题目描述

image

解法

类似链表删除结点,都是修改指针指向的结点,比如删除 4 结点,就需要将 4 节点之前的结点的指针,指向 4 的下一个结点。

解题的关键点就是找到结点的位置,并修改指针的指向,使用 node.next = node.next.next 即可修改指针的指向。找到结点的位置需要找到链表的长度,然后遍历链表,找到对应结点并修改指针。如果移除的是首结点,就找不到上一个结点,所以需要设置一个伪结点。总结一下解题思路:

  • 创建伪结点,next 指向链表。首结点就是一个为伪结点。
  • 遍历链表获取链表长度。
  • 获取结点位置就是 L-n+1。
  • 遍历链表,找到前一个结点的位置,也就是 L-n的结点的 next 指向 next.next.返回伪结点的 next 结点。

有了思路,写代码就快了:

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode cur = head;int length = 0;while(cur != null) {cur = cur.next;length++;}int index = 1;int sub = length - n + 1;ListNode dummy = new ListNode(1,head);cur = dummy;while(cur != null) {if(index == sub) {cur.next = cur.next.next;break;}cur = cur.next;index++;}return dummy.next;}
}

141.环形链表(简单)

题目描述

解法

环形链表表示链表的某个结点可以通过连续 next 指针再次被遍历到。所以需要做个查重的功能,如果存在重复的结点,就说明链表是一个环形链表。而查重使用 hash 表即可,汇总一下解题思路:

  • 遍历结点,将结点添加到 hash 表中。
  • 如果在添加数据时发现结点已存在,说明链表是环形链表。
public class Solution {public boolean hasCycle(ListNode head) {Set<ListNode> set = new HashSet<>();while (head != null) {if (!set.add(head)) {return true;}head = head.next;}return false;}
}

set 的 add 的方法判断是否存在相同的元素,其实是使用 HashMap 的 put 方法,返回之前的数据,如果之前数据不存在就返回 null。

21.合并两个有序链表(简单)

题目描述

解法

单链表查找结点是需要一个一个往后指针找结点,合并链表的,如果在原来的基础上添加结点就需要不断的遍历结点,合并的链表使用一个新的链表存储。首先找到最小的数据,然后结点存储到新链表,同时断开结点的 next。如下图所示。

先找到最小的结点,然后新链表(蓝色部分)指向小的结点,然后断开 next 指针。之后的重复类似的步骤。

需要考虑到如果某个链表遍历结束了,但是其他链表还有值,就需要遍历非空链表的数据了,最终总结题解的步骤:

  • 定义一个新的链表 node,存储合并的链表。
  • 找到最小的结点,新的链表的next 指向新的结点,并将找到的链表的 next 断开。
  • 重复遍历链表,找到最小的节点,直到某个链表为空。
  • 一个链表为空,另外不为空,就将链表直接赋值个新链表。

代码如下:

class Solution {public ListNode mergeTwoLists(ListNode l1, ListNode l2) {ListNode node = new ListNode(0);ListNode last = node;while (l1 != null && l2 != null) {if (l1.val < l2.val) {last.next = l1;l1 = l1.next;} else {last.next = l2;l2 = l2.next;}last = last.next;}if (l1 != null) {last.next = l1;}if (l2 != null) {last.next = l2;}return node.next;}
}

总结

链表相对数组来说,在定义的时候不需要确定好内存大小,因为链表的通过指针可以存储非连续空间的数据。链表的查询需要通过指针一个个找到对应的结点,而不能像数组一样通过索引直接找到对应的数据。在 JDK 中也会使用双链表,双链表更占内存,因为多了一个指针,带来的好处是查询数据可以从前往后查,也可以从后往前查,用空间换时间

主要介绍了几种常见的链表算法:

  • 反转链表
    • 反转指针方向,结点数据不会改变。 拆分一下数据,1—>2,先将 1 取出来,将 1 作为新链表的头结点,然后再将 2 取出,作为头结点,并指向新的 1,此时就完成 2 -> 1 的过程,后续结点以此类推。
  • 删除链表的倒数第 N 个结点
    • 关键点事要找到要删除的位置,倒数第 N 的节点,也就是链表长度 L-n+1,再修改指针,将自己上一个结点的指针指向自己节点的下一个结点
  • 环形链表
    • 环形链表表示存在相同的链表结点,遍历链表,存储在 hash 表,如果存在相同的结点就是环形链表。
  • 合并两个有序链表
    • 先找到两个链表最小的结点,新的链表指向最小结点,对应的链表去掉指向的结点,以此类推,直到遍历完某个链表。此时如果别的链表不为空,直接指向该链表。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/103759.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPS或EXCEL表格单元格下拉快捷选择项修改及设置方法

WPS或新版本EXCEL的设置下拉选项的方法是.点击一个单元格,菜单上选择数据,下拉列表即可设置,双击文字可编辑 EXCEL 旧的版本不同,可能有不同方法 方法一, 1.在空白区域里面&#xff0c;准备好需要填入下拉菜单里面的内容。 2.选中一个需要添加下拉菜单的单元格&#xff0c;然后…

MicroStation中将二维对象投射到三维实体

在三维建模中&#xff0c;偶而会遇到需要将一个2D对象沿Z轴或指定方向投射到一个3D实体&#xff0c;在3D实体表面生成这个2D对象的投影对象。 需要使用的操作命令为&#xff1a; Stencil 2D Elements on 3D Geometry&#xff0c;位于可视化工作流、实用工具栏内。 操作时先后选…

ChatGPT:深度学习和机器学习的知识桥梁

目录 ChatGPT简介 ChatGPT的特点 ChatGPT的应用领域 ChatGPT的工作原理 与ChatGPT的交互 ChatGPT的优势 ChatGPT在机器学习中的应用 ChatGPT在深度学习中的应用 总结 近年来&#xff0c;随着深度学习技术的不断发展&#xff0c;自然语言处理技术也取得了显著的进步。其…

More Effective C++学习笔记(5)

目录 条款25&#xff1a;将构造函数和非成员函数虚化条款26&#xff1a;限制某个类所能产生的对象数量条款27&#xff1a;要求&#xff08;或禁止&#xff09;对象产生于heap&#xff08;堆&#xff09;之中条款28&#xff1a;智能指针条款29&#xff1a;引用计数条款30&#x…

WIFI版本云音响设置教程阿里云平台版本

文章目录 WIFI本云音响设置教程介绍一、申请设备三元素1.登录阿里云物联网平台2.创建产品3.设置产品参数4.添加设备5.获取三元素 二、设置设备三元素1.打开MQTTConfigTools2.计算MQTT参数3.使用windows电脑的WIFI连接到设备热点4.设置参数5.配置设备连接路由器 三、阿里云物联网…

【校招VIP】测试算法考点之链表

考点介绍&#xff1a; 链表是一种逻辑简单的、实用的数据结构&#xff0c;几乎被所有程序设计语言支持。单链表的操作算法是笔试面试中较为常见的题目。 测试算法考点之链表-相关题目及解析内容可点击文章末尾链接查看&#xff01; 一、考点题目 1.一个长度为n的单向链表&am…

【创新项目探索】大数据服务omnidata-hive-connector介绍

omnidata-hive-connector介绍 omnidata-hive-connector是一种将大数据组件Hive的算子下推到存储节点上的服务&#xff0c;从而实现近数据计算&#xff0c;减少网络带宽&#xff0c;提升Hive的查询性能。目前支持Hive on Tez。omnidata-hive-connector已在openEuler社区开源。 …

哈希的应用——位图

文章目录 前言1. 面试题思考2. 位图2.1 位图的概念2.2 思路讲解及代码实现结构定义构造函数set和reset接口实现set和reset测试观察test接口实现test接口测试思考 3. 位图的应用&#xff08;海量数据处理面试题&#xff09;习题1习题2习题3 4. 总结5. 源码5.1 bitset.h5.2 Test.…

2023高教社杯数学建模国赛C题思路解析+代码+论文

如下为C君的2023高教社杯全国大学生数学建模竞赛C题思路分析代码论文 C题蔬菜类商品的自动定价与补货决策 在生鲜商超中&#xff0c;一般蔬菜类商品的保鲜期都比较短&#xff0c;且品相随销售时间的增加而变差, 大部分品种如当日未售出&#xff0c;隔日就无法再售。因此&…

MyBatis的逆向工程

文章目录 前言MyBatis的逆向工程创建逆向工程的步骤添加依赖和插件创建MyBatis的核心配置文件创建逆向工程的配置文件执行MBG插件的generate目标 QBC查询增改 总结 前言 MyBatis的逆向工程 正向工程&#xff1a;先创建Java实体类&#xff0c;由框架负责根据实体类生成数据库表…

TSN时间敏感网络

目录 时间敏感网络介绍 子协议介绍 时间同步 IEEE802.1AS 调度和流量整形 IEEE802.1Q IEEE802.1Qbv IEEE802.1cr IEEE802.1Qbu IEEE802.1Qch IEEE802.1Qav IEEE802.1Qcc 纠错机制与安全 IEEE802.1Qci IEEE802.1CB IEEE802.1Qca 参考 时间敏感网络介绍 TSN(Tim…

【Ambari】Python调用Rest API 获取集群状态信息并发送钉钉告警

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;开着拖拉机回家_大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341; 希望本文能够给您带来一定的帮助&#x1f338;文…