数据结构面试知识点总结3
#来自ウルトラマンティガ(迪迦)
1 线性表
最基本、最简单、最常用的一种数据结构。一个线性表是 n 个具有相同特性的数据元素的有限序列。
特征:数据元素之间是一对一的逻辑关系。
- 第一个数据元素没有前驱,称为头结点;
- 最后一个数据元素没有后继,称为尾结点;
- 除了头结点和尾结点,其他数据元素有且仅有一个前驱和一个后继。
分类:
- 顺序存储
- 链式存储
2 顺序表
顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元,依次存储线性表中的各个元素。
public class SequenceList<T> implements Iterable<T> {//存储元素的数组private T[] eles;//记录当前顺序表中的元素个数private int N;//构造方法public SequenceList(int capacity) {//初始化数组this.eles = (T[]) new Object[capacity];//初始化长度this.N = 0;}//将一个线性表置为空表public void clear() {this.N = 0;}//判断当前线性表是否为空表public boolean isEmpty() {return N == 0;}//获取线性表的长度public int length() {return N;}//获取指定位置的元素public T get(int i) {return eles[i];}//向线型表中添加元素 tpublic void insert(T t) {if (N == eles.length) {resize(2 * eles.length);}eles[N++] = t;}//在 i 元素处插入元素 tpublic void insert(int i, T t) {if (N == eles.length) {resize(2 * eles.length);}//先把i索引处的元素及其后面的元素依次向后移动一位for (int index = N; index > i; index--) {eles[index] = eles[index - 1];}//再把t元素放到i索引处即可eles[i] = t;//元素个数+1N++;}//删除指定位置i处的元素,并返回该元素public T remove(int i) {//记录索引i处的值T current = eles[i];//索引i后面元素依次向前移动一位即可for (int index = i; index < N - 1; index++) {eles[index] = eles[index + 1];}//元素个数-1N--;if (N < eles.length / 4) {resize(eles.length / 2);}return current;}//查找t元素第一次出现的位置public int indexOf(T t) {for (int i = 0; i < N; i++) {if (eles[i].equals(t)) {return i;}}return -1;}//根据参数newSize,重置eles的大小public void resize(int newSize) {//定义一个临时数组,指向原数组T[] temp = eles;//创建新数组eles = (T[]) new Object[newSize];//把原数组的数据拷贝到新数组即可for (int i = 0; i < N; i++) {eles[i] = temp[i];}}@Overridepublic Iterator<T> iterator() {return new SIterator();}private class SIterator implements Iterator {private int cursor;public SIterator() {this.cursor = 0;}@Overridepublic boolean hasNext() {return cursor < N;}@Overridepublic T next() {return eles[cursor++];}}
}
复杂度:
get(i):时间复杂度 O(1)
insert(int i, T t):时间复杂度 O(n)
remove(int i):时间复杂度 O(n)
3 链表
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列的结点(链表中的每一个元素称为结点)组成,结点可以在运行时动态生成。
//链表结点
public class Node<T> { //存储元素 public T item; //指向下一个结点 public Node next; public Node(T item, Node next) { this.item = item;this.next = next; }
}
复杂度:
get(i):时间复杂度 O(n)
insert(int i, T t):时间复杂度 O(1)
remove(int i):时间复杂度 O(1)
3.1 单向链表
单向链表是链表的一种,它由多个结点组成,每个结点都由一个数据域和一个指针域组成,数据域用来存储数据,指针域用来指向其后继结点。链表的头结点的数据域不存储数据,指针域指向第一个真正存储数据的结点。
public class LinkList<T> implements Iterable<T> {//头结点private Node head;//链表的长度private int N;//结点类private class Node {//存储数据T item;//下一个结点Node next;public Node(T item, Node next) {this.item = item;this.next = next;}}public LinkList() {//初始化头结点、this.head = new Node(null, null);//初始化元素个数this.N = 0;}//清空链表public void clear() {head.next = null;this.N = 0;}//获取链表的长度public int length() {return N;}//判断链表是否为空public boolean isEmpty() {return N == 0;}//获取指定位置i出的元素public T get(int i) {//通过循环,从头结点开始往后找,依次找i次,就可以找到对应的元素Node n = head.next;for (int index = 0; index < i; index++) {n = n.next;}return n.item;}//向链表中添加元素tpublic void insert(T t) {//找到当前最后一个结点Node n = head;while (n.next != null) {n = n.next;}//创建新结点,保存元素tNode newNode = new Node(t, null);//让当前最后一个结点指向新结点n.next = newNode;//元素的个数+1N++;}//向指定位置i出,添加元素tpublic void insert(int i, T t) {//找到i位置前一个结点Node pre = head;for (int index = 0; index <= i - 1; index++) {pre = pre.next;}//找到i位置的结点Node curr = pre.next;//创建新结点,并且新结点需要指向原来i位置的结点Node newNode = new Node(t, curr);//原来i位置的前一个节点指向新结点即可pre.next = newNode;//元素的个数+1N++;}//删除指定位置i处的元素,并返回被删除的元素public T remove(int i) {//找到i位置的前一个节点Node pre = head;for (int index = 0; index <= i - 1; i++) {pre = pre.next;}//要找到i位置的结点Node curr = pre.next;//找到i位置的下一个结点Node nextNode = curr.next;//前一个结点指向下一个结点pre.next = nextNode;//元素个数-1N--;return curr.item;}//查找元素t在链表中第一次出现的位置public int indexOf(T t) {//从头结点开始,依次找到每一个结点,取出item,和t比较,如果相同,就找到了Node n = head;for (int i = 0; n.next != null; i++) {n = n.next;if (n.item.equals(t)) {return i;}}return -1;}@Overridepublic Iterator<T> iterator() {return new LIterator();}private class LIterator implements Iterator {private Node n;public LIterator() {this.n = head;}@Overridepublic boolean hasNext() {return n.next != null;}@Overridepublic Object next() {n = n.next;return n.item;}}//用来反转整个链表public void reverse() {//判断当前链表是否为空链表,如果是空链表,则结束运行,如果不是,则调用重载的reverse方法完成反转if (isEmpty()) {return;}reverse(head.next);}//反转指定的结点curr,并把反转后的结点返回public Node reverse(Node curr) {if (curr.next == null) {head.next = curr;return curr;}//递归的反转当前结点curr的下一个结点;返回值就是链表反转后,当前结点的上一个结点Node pre = reverse(curr.next);//让返回的结点的下一个结点变为当前结点curr;pre.next = curr;//把当前结点的下一个结点变为nullcurr.next = null;return curr;}
}
3.2 双向链表
双向链表也叫双向表,是链表的一种,它由多个结点组成,每个结点都由一个数据域和两个指针域组成,数据域用来存储数据,其中一个指针域用来指向其后继结点,另一个指针域用来指向前驱结点。链表的头结点的数据域不存储数据,指向前驱结点的指针域值为null,指向后继结点的指针域指向第一个真正存储数据的结点。
public class TowWayLinkList<T> implements Iterable<T> {//首结点private Node head;//最后一个结点private Node last;//链表的长度private int N;//结点类private class Node {//存储数据T item;//指向上一个结点Node pre;//指向下一个结点Node next;public Node(T item, Node pre, Node next) {this.item = item;this.pre = pre;this.next = next;}}public TowWayLinkList() {//初始化头结点和尾结点this.head = new Node(null, null, null);this.last = null;//初始化元素个数this.N = 0;}//清空链表public void clear() {this.head.next = null;this.head.pre = null;this.head.item = null;this.last = null;this.N = 0;}//获取链表长度public int length() {return N;}//判断链表是否为空public boolean isEmpty() {return N == 0;}//获取第一个元素public T getFirst() {if (isEmpty()) {return null;}return head.next.item;}//获取最后一个元素public T getLast() {if (isEmpty()) {return null;}return last.item;}//插入元素tpublic void insert(T t) {if (isEmpty()) {//如果链表为空://创建新的结点Node newNode = new Node(t, head, null);//让新结点称为尾结点last = newNode;//让头结点指向尾结点head.next = last;} else {//如果链表不为空Node oldLast = last;//创建新的结点Node newNode = new Node(t, oldLast, null);//让当前的尾结点指向新结点oldLast.next = newNode;//让新结点称为尾结点last = newNode;}//元素个数+1N++;}//向指定位置i处插入元素tpublic void insert(int i, T t) {//找到i位置的前一个结点Node pre = head;for (int index = 0; index < i; index++) {pre = pre.next;}//找到i位置的结点Node curr = pre.next;//创建新结点Node newNode = new Node(t, pre, curr);//让i位置的前一个结点的下一个结点变为新结点pre.next = newNode;//让i位置的前一个结点变为新结点curr.pre = newNode;//元素个数+1N++;}//获取指定位置i处的元素public T get(int i) {Node n = head.next;for (int index = 0; index < i; index++) {n = n.next;}return n.item;}//找到元素t在链表中第一次出现的位置public int indexOf(T t) {Node n = head;for (int i = 0; n.next != null; i++) {n = n.next;if (n.next.equals(t)) {return i;}}return -1;}//删除位置i处的元素,并返回该元素public T remove(int i) {//找到i位置的前一个结点Node pre = head;for (int index = 0; index < i; index++) {pre = pre.next;}//找到i位置的结点Node curr = pre.next;//找到i位置的下一个结点Node nextNode = curr.next;//让i位置的前一个结点的下一个结点变为i位置的下一个结点pre.next = nextNode;//让i位置的下一个结点的上一个结点变为i位置的前一个结点nextNode.pre = pre;//元素的个数-1N--;return curr.item;}@Overridepublic Iterator<T> iterator() {return new TIterator();}private class TIterator implements Iterator {private Node n;public TIterator() {this.n = head;}@Overridepublic boolean hasNext() {return n.next != null;}@Overridepublic Object next() {n = n.next;return n.item;}}
}
3.3 循环链表
链表整体要形成一个圆环状。让单向链表的最后一个节点的指针指向头结点。
4 题目
4.1 反转链表
LeetCode:24 题
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
示例:
输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
class Solution {public ListNode reverseList(ListNode head) {ListNode pre = null;ListNode cur = head;while(cur != null) {ListNode tmp = cur.next;cur.next = pre;pre = cur;cur = tmp;}return pre;}
}
4.2 快慢指针
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
示例:
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。
public class Solution {public boolean hasCycle(ListNode head) {//快慢指针if(head == null || head.next == null) return false;ListNode slow = head;ListNode fast = head.next;while(slow != fast){if(fast == null || fast.next == null) return false;slow = slow.next;fast = fast.next.next;}return true;}
}相关文章:
数据结构面试知识点总结3
#来自ウルトラマンティガ(迪迦) 1 线性表 最基本、最简单、最常用的一种数据结构。一个线性表是 n 个具有相同特性的数据元素的有限序列。 特征:数据元素之间是一对一的逻辑关系。 第一个数据元素没有前驱,称为头结点࿱…...
python-爬虫实例(5):将进酒,杯莫停!
目录 前言 将进酒,杯莫停! 一、浇给 二、前摇 1.导入selenium库 2.下载浏览器驱动 三、爬虫四步走 1.UA伪装 2.获取url 3.发送请求 4.获取响应数据进行解析并保存 总结 前言 博主身为一个农批,当然要尝试爬取王者荣耀的东西啦。 将进…...
AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理
AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理 目录 AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理 一、简单介绍 二、Transformer 1、模型架构 2、应用场景 3、Hugging …...
十大排序的稳定性和时间复杂度
十大排序算法的稳定性和时间复杂度是数据结构和算法中的重要内容。 以下是对这些算法的稳定性和时间复杂度的详细分析: 稳定性 稳定性指的是排序算法在排序过程中是否能够保持相等元素的原始相对顺序。根据这个定义,我们可以将排序算法分为稳定排序和…...
【系列教程之】1、点亮一个LED灯
1、点亮一个LED灯 作者将狼才鲸创建日期2024-07-23 CSDN教程目录地址:【目录】8051汇编与C语言系列教程本Gitee仓库原始地址:才鲸嵌入式/8051_c51_单片机从汇编到C_从Boot到应用实践教程 本源码包含C语言和汇编工程,能直接在电脑中通过Keil…...
搜维尔科技:Manus Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作
Manus Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作 搜维尔科技:Manus Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作...
机器学习 | 阿里云安全恶意程序检测
目录 一、数据探索1.1 数据说明1.2 训练集数据探索1.2.1 数据特征类型1.2.2 数据分布1.2.3 缺失值1.2.4 异常值1.2.5 标签分布探索 1.3 测试集探索1.3.1 数据信息1.3.2 缺失值1.3.3 数据分布1.3.4 异常值 1.4 数据集联合分析1.4.1 file_id 分析1.4.2 API 分析 二、特征工程与基…...
python打包exe文件-实现记录
1、使用pyinstaller库 安装库: pip install pyinstaller打包命令标注主入库程序: pyinstaller -F.\程序入口文件.py 出现了一个问题就是我在打包运行之后会出现有一些插件没有被打包。 解决问题: 通过添加--hidden-importcomtypes.strea…...
基本的DQL语句-单表查询
一、DQL语言 DQL(Data Query Language 数据查询语言)。用途是查询数据库数据,如SELECT语句。是SQL语句 中最核心、最重要的语句,也是使用频率最高的语句。其中,可以根据表的结构和关系分为单表查询和多 表联查。 注意:所有的查询…...
Vue3 对比 Vue2
相关信息简介2020年9月18日,Vue.js发布3.0版本,代号:One Piece(海贼王) 2 年多开发, 100位贡献者, 2600次提交, 600次 PR、30个RFC Vue3 支持 vue2 的大多数特性 可以更好的支持 Typescript,提供了完整的…...
2024中国大学生算法设计超级联赛(1)
🚀欢迎来到本文🚀 🍉个人简介:陈童学哦,彩笔ACMer一枚。 🏀所属专栏:杭电多校集训 本文用于记录回顾总结解题思路便于加深理解。 📢📢📢传送门 A - 循环位移解…...
offer题目51:数组中的逆序对
题目描述:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如,在数组{7,5,6,4}中,一共存在5个逆序对,分别是(7…...
45、PHP 实现滑动窗口的最大值
题目: PHP 实现滑动窗口的最大值 描述: 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。 例如: 如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3, 那么一共存在6个滑动窗口, 他们的最大值…...
【计算机视觉】siamfc论文复现实现目标追踪
什么是目标跟踪 使用视频序列第一帧的图像(包括bounding box的位置),来找出目标出现在后序帧位置的一种方法。 什么是孪生网络结构 孪生网络结构其思想是将一个训练样本(已知类别)和一个测试样本(未知类别)输入到两个CNN(这两个CNN往往是权值共享的)中࿰…...
数学建模学习(111):改进遗传算法(引入模拟退火、轮盘赌和网格搜索)求解JSP问题
文章目录 一、车间调度问题1.1目前处理方法1.2简单案例 二、基于改进遗传算法求解车间调度2.1车间调度背景介绍2.2遗传算法介绍2.2.1基本流程2.2.2遗传算法的基本操作和公式2.2.3遗传算法的优势2.2.4遗传算法的不足 2.3讲解本文思路及代码2.4算法执行结果: 三、本文…...
Golang | Leetcode Golang题解之第241题为运算表达式设计优先级
题目: 题解: const addition, subtraction, multiplication -1, -2, -3func diffWaysToCompute(expression string) []int {ops : []int{}for i, n : 0, len(expression); i < n; {if unicode.IsDigit(rune(expression[i])) {x : 0for ; i < n &…...
Unity客户端接入原生Google支付
Unity客户端接入原生Google支付 1. Google后台配置2. 开始接入Java部分C#部分Lua部分 3. 导出工程打包测试参考踩坑注意 1. Google后台配置 找到内部测试(这个测试轨道过审最快),打包上传,这个包不需要接入支付,如果已…...
Spring Cloud之五大组件
Spring Cloud 是一系列框架的有序集合,为开发者提供了快速构建分布式系统的工具。这些组件可以帮助开发者做服务发现,配置管理,负载均衡,断路器,智能路由,微代理,控制总线等。以下是 Spring Cl…...
在 CentOS 7 上安装 Docker 并安装和部署 .NET Core 3.1
1. 安装 Docker 步骤 1.1:更新包索引并安装依赖包 先安装yum的扩展,yum-utils提供了一些额外的工具,这些工具可以执行比基本yum命令更复杂的任务 sudo yum install -y yum-utils sudo yum update -y #更新系统上已安装的所有软件包到最新…...
redis的学习(一):下载安装启动连接
简介 redis的下载,安装,启动,连接使用 nosql nosql,即非关系型数据库,和传统的关系型数据库的对比: sqlnosql数据结构结构化非结构化数据关联关联的非关联的查询方式sql查询非sql查询事务特性acidbase存…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
