数据结构
文章平均质量分 57
包括了基本数据结构的特性分析,Java实现,以及LeetCode习题示例
A minor
本来无一物,何处惹尘埃
展开
-
【数据结构】数组:特性浅析
1 数组是什么数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。1.1 线性表结构数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。线性表(Linear List):顾名思义,线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。其实除了数组,链表、队列、栈等也是线性表结构。非线性表:是与线性表相对的概念,如二叉树、堆、图等。之所以叫非线性,是因为,在非线性表中,数据之间并不是简单的原创 2020-09-17 19:15:53 · 1302 阅读 · 0 评论 -
【数据结构】数组:Java实现数组动态扩容(150行代码仿写ArrayList)
在文章开头先放一个传送门 【Java容器源码】ArrayList源码分析。是作者写的关于LInkedList源码的分析。这篇文章就仿写ArrayList,并实现容器中的核心方法。1.ArrayList基本结构public class MyArrayList<E> { private static final int DEFAULT_CAPACITY = 10; // 第一次扩容时的容量 private static final Object[] EMPTY_ELEMENT原创 2020-09-21 17:01:39 · 1868 阅读 · 0 评论 -
【数据结构】数组:LeetCode题(一)11.盛水最多的容器,283.移动零,15.三数之和
时间 & 空间空间换时间用空间换时间的设计思想。当内存空间充足的时候,如果我们更加追求代码的执行速度,我们就可以选择空间复杂度相对较高、但时间复杂度相对很低的算法或者数据结构。缓存实际上就是利用了空间换时间的设计思想。如果我们把数据存储 在硬盘上,会比较节省内存,但每次查找数据都要询问一次硬盘,会比较慢。但如果我们通 过缓存技术,事先将数据加载在内存中,虽然会比较耗费内存空间,但是每次数据查询的速 度就大大提高了数据结构中双向链表正是用了空间换时间,提高了crud的效率时间换空间如原创 2020-09-18 20:37:18 · 1956 阅读 · 0 评论 -
【数据结构】数组:LeetCode题(二)88.合并两个有序数组,4.两个正序数组的中位数
88. 合并两个有序数组¹给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中*,*使 nums1 成为一个有序数组。说明:初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。示例:输入:nums1 = [1,2,3,0,0,0], m = 3nums2 = [2,5,6], n = 3输出: [1,2,2,3,5,6原创 2020-09-22 19:25:57 · 1270 阅读 · 1 评论 -
【数据结构】数组:二维数组填数问题,蛇形填数三变式及杨辉三角
1.基础填数如下图,第20行第20个数是什么?1 2 4 7 113 5 8 126 9 1310 1415思路:如果想一行一行或者一列一列的填,那肯定就很难想。但是斜着看就很简单了。所以思路就出来了,一次填一个对角线。那问题又来了,由于不是每条对角线上都有行=列的点,所以第20行20列的数在哪个对角线上呢?从上面的图可以分析出,行=列的元素一定在第奇数条对角线,比如(1,1)=1在第一条,(2,2)=5在第三条。所以可以得到2n-1的关系,即(20,20)在第39条原创 2020-11-02 20:13:35 · 1189 阅读 · 0 评论 -
【数据结构】链表:特性浅析
1.底层存储结构数组需要一块连续的内存空间来存储, 对内存的要求比较高。如果我们申请一个 100MB 大小的数组,当内存中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于 100MB,仍然会申请失败。而链表恰恰相反,它并不需要一块连续的内存空间,它通过“指针”将一组零散的内存块串联起来使用,所以如果我们申请的是 100MB 大小的链表,根本不会有问题。2.链表分类2.1 单链表将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的下一个结点的地址。如图所示,我们把这个原创 2020-09-21 15:23:05 · 2143 阅读 · 1 评论 -
【数据结构】链表:Java实现双向链表(200行代码仿写LinkedList)
文章开头先放一个传送门【Java容器源码】LinkedList源码分析,是作者写的关于LInkedList源码的分析。这篇文章就模仿LinkedList,并实现容器中的核心方法。1.Node在LinkedList容器中,底层是通过双向链表实现的,所以有next与prev两个指针public class MyLinkedList<E> { // 容器是有泛型的,Node也应该有泛型 private static class Node<E> { E原创 2020-09-21 16:14:56 · 2847 阅读 · 3 评论 -
【数据结构】链表:LeetCode题(一)206.反转链表,24.两两交换相邻节点
在讲解链表的LeetCode题之前先说几点注意:head指针与p指针:head 指针指向参数链表的头,用于标识链表p 指针一般是 p = head,用于操作链表两者都可以变,都可以用来操作当前链表。但若只是内部操作,即操作完后还要返回原链表,比如删除指定节点,然后返回链表,就必须要返回head。推荐每次链表传来先 p = head ,然后拿p去操作链表,若head无用再考虑将p替换有头链表与无头链表在遍历时的区别:有头链表:while (p.next != null)无头链表:原创 2020-09-22 19:18:34 · 2263 阅读 · 0 评论 -
【数据结构】链表:LeetCode题(二)141.环形链表I,142.环形链表II
141.环形链表¹给定一个链表,判断链表中是否有环。为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环示例 1:输入:head = [3,2,0,-4], pos = 1输出:true解释:链表中有一个环,其尾部连接到第二个节点。示例 2:输入:head = [1,2], pos = 0输出:true解释:链表中有一个环,其尾部连接到第一个节点。示例 3:输入:head = [1],原创 2020-09-22 20:00:09 · 884 阅读 · 0 评论 -
【数据结构】链表:LeetCode题(三)21.合并两个有序链表
21. 合并两个有序链表¹将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例:输入:1->2->4, 1->3->4输出:1->1->2->3->4->4解法一:双指针(归并)思路:新建一个头,链表1,链表2比大小插入即可。就像归并排序中合并两个子数组一样。注:这里能这么做的前提一定是待合并的两部分是排好序的!!复杂度Time:O(m + n)Space:O(1)publ原创 2021-02-26 01:31:15 · 170 阅读 · 0 评论 -
【数据结构】链表:LeetCode题(四)234.回文链表
234. 回文链表请判断一个链表是否为回文链表。示例 1:输入: 1->2输出: false示例 2:输入: 1->2->2->1输出: true解法一:栈思路:遍历链表,将所有节点压入栈,再遍历一遍进行对比注:栈里应该存的是val,而不是ListNode,因为比较的时候顺序是相反的,ListNode肯定都不相同。复杂度Time:O(n)Space:O(n),用了个Stackpublic boolean isPalindrome(ListNo原创 2021-02-26 01:32:40 · 74 阅读 · 0 评论 -
【数据结构】栈:Java实现顺序栈&栈应用浅析
1.栈是什么定义:后进者先出,先进者后出,这就是典型的“栈”结构操作特性:栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。使用场景;当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,就应该首选“栈”这种数据结构。2.Java实现顺序栈用数组实现的栈,我们叫作顺序栈(效率高),而用链表实现的栈,我们叫作链式栈。2.1 固定大小的栈时间复杂度:O(1),每次都只操作count(-1)位,与数据规模无关空间复杂度:O(1),最开始申请了固定大小数组后运行时原创 2020-09-26 01:56:46 · 2888 阅读 · 0 评论 -
【数据结构】栈:LeetCode题 20.有效的括号,155.最小栈,84.柱状图的最大矩形
20.有效的括号¹给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。注意空字符串可被认为是有效字符串。示例 1:输入: "()"输出: true示例 2:输入: "()[]{}"输出: true示例 3:输入: "(]"输出: false示例 4:输入: "([)]"输出: false示例 5:输入: "{[]}"输出: true原创 2020-09-26 03:06:34 · 2225 阅读 · 0 评论 -
【数据结构】队列:Java实现循环队列&链式队列
1.顺序队列(循环)基于数组的循环队列其实很简单,就是当数组满后重置入队和出队位置到数组头部。public class CircleQueue<E> { // Object保存E,因为E不能E[] --> (E)obj private Object[] items; private int putIdx; // 实际入队位置 private int takeIdx; // 实际出队位置 private int count; // 队列中元素打原创 2020-09-26 03:29:08 · 1414 阅读 · 0 评论 -
【数据结构】散列表:从特性分析到散列冲突再到应用总结
1.散列表是什么散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。1.1 散列表与数组从上面对散列表的定义可以看到,散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。与数组的区别在于:使用数组时,我们一般按序放入,即 for(i) arr[i]使用原创 2020-10-04 18:00:38 · 1193 阅读 · 0 评论 -
【数据结构】散列表:LeetCode题(一)242. 有效的字母异位词,49. 字母异位词分组
在看散列表相关LeetCode题之前,先放个传送门【数据结构】散列表,从特性分析到散列冲突再到应用总结…242. 有效的字母异位词¹给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。示例 1:输入: s = "anagram", t = "nagaram"输出: true示例 2:输入: s = "rat", t = "car"输出: false说明:你可以假设字符串只包含小写字母。异位词:组成相同,顺序不同解法一:双重循环思路:对s的每个字母,原创 2020-10-05 16:58:22 · 2044 阅读 · 0 评论 -
【数据结构】散列表:LeetCode题(二)1. 两数之和,13. 罗马数字转整数
1. 两数之和¹给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。示例:给定 nums = [2, 7, 11, 15], target = 9因为 nums[0] + nums[1] = 2 + 7 = 9所以返回 [0, 1]1.解法一:枚举法思路:没啥说的,就是枚举出所有结果复杂度Time:O(n^2),66msSpace原创 2021-02-26 01:37:06 · 126 阅读 · 0 评论 -
【数据结构】跳表:Skip List 特性浅析
1.跳表 = 有序链表+多级索引对于一个单链表来讲,即便链表中存储的数据是有序的,如果我们要想在其中查找某个数据,也只能从头到尾遍历链表。这样查找效率就会很低,时间复杂度会很高,是 O(n)。下面我们就通过4张图片看看如何从链表转化成跳表:2.时间复杂度分析2.1 查询:O(logn))按照我们刚才分析的,每两个结点会抽出一个结点作为上一级索引的结点,那第一级索引的结点个数大约就是 n/2,第二级索引的结点个数大约就是 n/4,第三级索引的结点个数大约就 是 n/8,依次类推,也就是说,第原创 2020-10-05 20:35:04 · 1018 阅读 · 0 评论 -
【数据结构】二叉树:特性浅析及Java实现五种遍历
1.基本概念1.1 节点这里放一张图,我们对着这张图来介绍:A 节点就是 B 节点的父节点,B 节点是 A 节点的子节点B、C、D 这三 个节点的父节点是同一个节点,所以它们之间互称为兄弟节点我们把没有父节点的节点叫 作根节点,也就是图中的节点 E我们把没有子节点的节点叫作叶子节点或者叶节点,比如 图中的 G、H、I、J、K、L 都是叶子节点1.2 高 / 深度节点的高度:节点到叶子节点的最长路径(边数)树的高度:根节点的高度节点的深度:根节点到这个节点所经历的边数个数节点的层原创 2020-10-05 23:31:03 · 986 阅读 · 0 评论 -
【数据结构】二叉树:AVL树与红黑树特性浅析(图解)
1.AVL树1.1 基本概念发明者:G.M.Adlson-Velsky 和 Evgenii Landis 所以称之为 AVL 树优点:AVL树是带有平衡条件的查找二叉树。他保证树的深度为O(logN),查找复杂度O(logN)缺点:要不断旋转来保证平衡,在多增删情况下耗费资源大 —> 近似平衡树1.2 平衡因子:判断平衡的标准平衡因子 = 左子树高度 - 右子树高度(有时相反)取值: { -1,0,1}AVL树所有节点的平衡因子必须是{-1,0,1},在CRUD时要维护节点原创 2020-10-06 03:00:44 · 1117 阅读 · 0 评论 -
【数据结构】二叉树:Java实现二叉查找树(附过程图解)
二叉查找树(BST):在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值,而右子树节点的值都大于这个节点的值public class BinarySearchTree { class Node { int item; Node left; Node right; public Node(int item) { this.item = item; } } // 标原创 2020-10-06 00:38:48 · 1637 阅读 · 0 评论 -
【数据结构】二叉树:LeetCode题(一)94. 二叉树的中序遍历,144. 二叉树的前序遍历,145. 二叉树的后序遍历,102. 二叉树的层序遍历
文章开始前,先放个传送门 二叉树特性浅析及Java实现DFS、BFS。那么,这篇我们就来看看二叉树在LeetCode最基本的三个题:中序遍历,前序遍历,后序遍历。其实解法真么什么说的了,都是八股文…94. 二叉树的中序遍历²给定一个二叉树,返回它的中序 遍历。示例:输入: [1,null,2,3] 1 \ 2 / 3输出: [1,3,2]解法一:递归中序:左根右,将根换成add()就行class Solution { public List&原创 2020-10-06 20:10:39 · 1573 阅读 · 0 评论 -
【数据结构】二叉树:LeetCode题(二)589. N叉树的前序遍历,590. N叉树的后序遍历,429. N叉树的层序遍历
在上一篇 二叉树的LeetCode题(一):94. 二叉树的中序遍历,144. 二叉树的前序遍历,145. 二叉树的后序遍历,102. 二叉树的层序遍历 中我们看到了LeetCode中关于二叉树的基本问题,本篇我们就来看看N叉树的基本问题。589. N叉树的前序遍历¹给定一个 N 叉树,返回其节点值的前序遍历。例如,给定一个 3叉树 :返回其前序遍历: [1,3,5,6,2,4]。解法一:递归class Solution { public List<Integer> pre原创 2020-10-06 21:34:32 · 1970 阅读 · 0 评论 -
【数据结构】二叉树:LeetCode题(三)226. 翻转二叉树,104.二叉树的最大深度,111.二叉树的最小深度
226. 翻转二叉树¹翻转一棵二叉树。示例:输入: 4 / \ 2 7 / \ / \1 3 6 9输出: 4 / \ 7 2 / \ / \9 6 3 1解法一:递归public TreeNode invertTree(TreeNode root) { if (root == null) return root; TreeNode tmp = root.left;原创 2020-10-14 15:51:29 · 1493 阅读 · 0 评论 -
【数据结构】二叉树:LeetCode题(四)100. 相同的树,98. 验证二叉搜索树,28. 对称的二叉树
28. 对称的二叉树¹请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 1 / \ 2 2 / \ / \3 4 4 3但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: 1 / \ 2 2 \ \ 3 3示例 1:输入:root = [1,2,2,3,4,4,3]输出:true示例 2:原创 2020-10-06 21:54:19 · 1318 阅读 · 0 评论 -
【数据结构】二叉堆:Java实现最大堆及堆排序
堆在逻辑上一棵完全二叉树,所以可以通过数组进行数据存储,而其余的树大多采用链式结构进行数据存储堆分类:大顶堆:大顶堆就是无论在任何一棵(子)树中,父节点都是最大的小顶堆:小顶堆就是无论在任何一棵(子)树中,父节点都是最小的。PriortyQueue 采用的就是小顶堆堆的两种操作:上浮:一般用于向堆中添加新元素后的堆平衡下沉:一般用于取出堆顶并将堆尾换至堆顶后的堆平衡堆排序:利用大顶堆和小顶堆的特性,不断取出堆顶,取出的元素就是堆中元素的最值,然后再使堆平衡下面的文章以大顶堆为原创 2020-09-29 00:09:06 · 1649 阅读 · 0 评论 -
【数据结构】并查集:Java实现并查集
并查集是一种树形的数据结构,顾名思义,它用于处理一些不交集的 合并 及 查询 问题。 它支持两种操作:查找(Find):确定某个元素处于哪个子集,或者判断某一元素是否属于当前集合合并(Union):将两个子集合并成一个集合下面我们就来看看如何用Java实现并查集…1.初始化public class UnionFind{ // 记录有多少个小集合 private int count = 0; // 元素 i 的父元素(有点桶排序的意思,即下标有实际意义) priv原创 2020-10-06 18:07:49 · 1251 阅读 · 2 评论 -
【数据结构】并查集:LeetCode题 547.朋友圈问题
547. 朋友圈班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。示例 1:输入: [[1,1,0], [1,1,0], [0,0,1]]输出: 2 说明原创 2021-02-26 01:59:03 · 699 阅读 · 0 评论 -
【数据结构】布隆过滤器:BloomFilter原理及Java实现
1.原理布隆过滤器(Bloom Filter)核心实现是一个超大的位数组和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k以上图为例,具体的操作流程:假设集合里面有3个元素{x, y, z},哈希函数的个数为3。数组置0:首先将位数组进行初始化,将里面每个位都设置位0。hash标1:对于集合里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数组上面的一个点,然后将位数组对应的位置标记为1。逐一比对:查询W元素是否存在集合中的时候,同原创 2020-10-06 16:43:27 · 3548 阅读 · 0 评论 -
【数据结构】LRU,从O(n)复杂度到O(1)
Last Recently Used1.单链表(O(n))单向链表,从head出,tail进入(理解成队列,左进(tail)右出(head)查找查找:遍历得到这个数据对应的结点移动:将其从原来的位置删除,然后再插入到链表的头部删除查找:遍历找到要删除节点删除:用前驱节点删除添加:查找 + (移动/删除)存在:移动懂到头不存在缓存未满,则将此结点直接插入到链表的头部缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部这三个操作都要涉及“查找”操作如原创 2020-11-22 21:54:40 · 1902 阅读 · 1 评论