数据结构与算法
文章平均质量分 70
圣斗士Morty
Java开发者,技术学习爱好者,费曼技巧学习法践行者
展开
-
排序算法 —— 计数排序
引言原创 2021-05-30 13:48:59 · 276 阅读 · 0 评论 -
经典数据结构——前缀树
引言前缀树——trie 树,也叫作“单词查找树”、“字典树”。它属于多叉树结构,典型应用场景是统计原创 2021-05-29 22:56:07 · 6808 阅读 · 0 评论 -
排序算法 —— 堆排序
引言此文基于《经典数据结构——堆的实现》中堆结构,实现一个以堆处理排序的算法。一、算法思想基于堆结构的堆排序的算法思想非常简单,循环获取大根堆中的最大值(0位置的根节点)放到堆的末尾,直到将堆拿空。由于一个现成的大根堆可以实现 O(1) 时间复杂度的最大值返回,因此堆排序的主要时间消耗就是在 heapInsert 或 heapify 这类维护大根堆结构的过程上。二、代码演示首先将数组从0开始,模拟逐个放入的过程,循环 heapInsert 建堆。然后以整个数组为堆,模拟循环取原创 2021-05-22 11:43:00 · 372 阅读 · 0 评论 -
经典数据结构——堆的实现
一、完全二叉树堆是一种完全二叉树,什么是完全二叉树?简单的说,一棵满二叉树表示的是所有节点全部饱和,最后一层全部占满:而完全二叉树指的是满二叉树的最后一层,所有叶子节点都从左往顺序排满:完全二叉树的特点非常简单,除了最后一层,其他各层节点都是满的,而最后一层,所有要求所有节点从左往右依次排满。它并不关心节点元素的大小,只与这一特定结构有关。二、堆结构前面说到,堆是一种特殊的完全二叉树,除了符合完全二叉树的结构特点,它还有另一个特性,由这个特性,我们又可以将堆分为——大根堆、小原创 2021-05-15 23:12:35 · 872 阅读 · 0 评论 -
比较器的使用
一、TreeMap 实现排序TreeMap是一个有序结构,TreeSet也是类似。他们可以实现对元素的排序。TreeMap 是针对 key进行排序。如果TreeMap的key 是Integer类型,可以无需指定任何特殊条件,默认即按照升序进行排序,如: public static void main(String[] args) { Object value = new Object(); TreeMap<Integer, Object>原创 2021-05-15 16:31:51 · 649 阅读 · 0 评论 -
排序算法——随机快速排序
引言随机快排是一个非常有意思的排序排序算法,它的算法思想用到了如递归、荷兰国旗问题等诸多元素,还意外的引入了随机性的概念。以下将逐步总结三个版本的快速排序,由浅入深总结快速排序的经典实现过程。荷兰国旗问题参考:《荷兰国旗问题》一、快速排序1.0在荷兰国旗问题中,我们通过简单的逻辑可以将一个数组分为两个区域或三个区域,但往往需要在题目之初给定一个 target 作为目标数以此划分。而在快速排序算法中,这个 target 选为排序范围上的最右边的数——arr[R],我们以 R 上的数为原创 2021-04-26 20:15:27 · 5472 阅读 · 0 评论 -
荷兰国旗问题
一、问题描述荷兰国旗问题,顾名思义,就是按照荷兰国旗的形式,给定一个数 x ,将 <x 的数放到左边,=x 的数放中间,>x 的数放右边,将数组中的元素分成三块,有的时候可能要求 <= x 的放左边:二、解题思路首先,数组是无序的,如果要求 <= x 放左边,>x 的放右边,将数组分成两部分,该如何做?我们应当在数组的左边设定一个指针,指针位置以左,代表 <=x 的区域,然后再设计一个指针代表当前数 ,如果当前数 <=x,当前数与 <= .原创 2021-04-25 21:36:34 · 391 阅读 · 0 评论 -
排序算法——归并排序的相关问题
一、小和问题问题描述,给定一个数组,如[1, 3, 2, 6, 5],计算每个数左边小于自己的所有数的和,并累加。例如:1左边没有数3左边有一个小于自己的数 12左边有一个小于自己的数 16左边有三个小于自己的数 1 + 3 + 2 = 65左边有三个小于自己的数 1 + 3 + 2 = 6最后 1 + 1 + 6 + 6 = 14,上面给定数组[1, 3, 2, 6, 5] 的小和解就是 14.解题思路:这道题的常规思路是循环每个数,然后再遍历它左边的所有数,只要比自.原创 2021-04-20 21:03:17 · 618 阅读 · 1 评论 -
排序算法——归并排序
引言归并排序可以使用递归或迭代的方式来实现,时间复杂度是都是O(N * logN)。归并排序的核心是将待排序数组分组,可以整体二分,也可以设置步长迭代切分。归并排序在操作过程中,充分利用了上一次排序的结果,而 O(N ^ 2)的排序算法每次比较都是独立的,简单的说就是,上一次的比较行为完全和下次比较行为无关,这在一定程度上浪费了比较的既得结果。一、递归实现不论是递归还是迭代,归并排序最重要的部分是实现两个分组的归并,在归并的过程中同时做好排序。整个过程可以分为两个大的部分:迭代过程.原创 2021-04-11 21:09:46 · 441 阅读 · 0 评论 -
算法设计中的基础常用代码
引言本篇博客旨在记录一些基础算法知识的常见组合用法,以及何时使用,需要注意的问题等,长期更新。为什么要这样总结呢?难道掌握了位运算、常用算法工具API的定义还不够吗?这是因为某些知识比如 &、 |、 ~、 Math.random 等这些基础知识如果只停留在知识记忆层面还是无法快速运用到算法的解题思路中去,还应该有一套常见组合用法或使用规律。这些组合用法通常并不是算法题的核心考点,但却起到连接算法思想、基础知识和解题实现的枢纽作用,就好比学习英语时,我们的目的是连词成句,但单词并不是简原创 2021-04-05 15:50:07 · 596 阅读 · 0 评论 -
递归算法及其时间复杂度分析
引言“递归” 一词是比较专业的计算机术语,在现实生活中,有一个更可爱的词——“套娃”。如果把“递归算法”叫做“套娃算法”,或许可以减少一些恐惧程度。套娃是有限的,同样,递归也是有限的,这和我们经常在影视作品中看到的“无限嵌套循环”是有很大区别的,递归一定存在某个可以返回的节点或条件,否则就会出现栈溢出错误(StackOverflowError)。其实“套娃”这个词已经足以概括递归算法的本质,就是函数本身调用自身,直到找到一个可以返回的条件,再层层返回。参考《盗梦空间》《明日边缘》等。递归算法原创 2021-04-05 13:01:24 · 5525 阅读 · 2 评论 -
单向队列、双端队列、栈的模型实现
引言自己实现简单的队列、栈的逻辑结构。队列都包含头和尾两个指针,简单的单向队列只能在一端(如:head端)入列,在另一端(如:tail 端)出列;双端队列可以在 head 进出,也可以在 tail 进出。栈的模型更加简单,它分为 top 和 bottom 两个指针,只能在 top 端进出。经典的模型结构包含几个主要方法,进、出、isEmpty、size 等。一、队列的实现不论是单向队列还是双端队列,始终都是在操作 head 和 tail 两个指针。它们的实现没有什么本质区别,实际上,原创 2021-04-04 18:25:33 · 446 阅读 · 0 评论 -
链表的基本操作——反转与删除
引言链表相关的问题几乎都是coding问题,以下是两个简单的链表问题。一、单链表或双链表如何反转1.1 单链表的反转操作给定一个 Node 结构:public static class Node { public int value; public Node next; public Node(int data) { this.value = data; }}这是一个单链表结构, 假设初始时,a --> b --> c原创 2021-04-03 19:54:04 · 328 阅读 · 0 评论 -
异或运算的应用
一、基础知识异或运算,相异为1。异或运算是一种常用的位运算,在算法题中,对于避免额外的空间复杂度有独特的用处。异或运算也被称为“无进位相加”,它具有以下特性:特性1:0 ^ N = N特性2:N ^ N = 0特性3(交换律):a ^ b = b ^ a特性4(结合律):(a ^ b) ^ c = a ^ (b ^ c)特性3 和 4总结起来,就是同一批数,不论使用怎样的顺序,怎样的结合方式进行异或,其结果始终一样。二、算法题题目1:如何不使用额外空间交换两个数?原创 2021-04-03 10:52:13 · 1062 阅读 · 0 评论 -
查找算法——二分法
引言二分法,顾名思义,即一分为二的方法,通常用于判断在某个有序数列中是否存在某个数,由于其优秀的算法思想,时间复杂度一般都是 O(logN) ,通常要 O(N) 的遍历方式更加优秀。一、经典二分法查找最常见的二分查找是有序数列找某数,但并不是所有二分查找都必须有序。public static boolean exist(int[] sortedArr, int num) { if (sortedArr == null || sortedArr.length == 0)原创 2021-03-27 14:56:37 · 465 阅读 · 0 评论 -
排序算法——对数器
引言所谓“对数器”就是校验算法的工具程序,我们使用Math.random() 方法可以生成一个随机乱序数组,并通过Arrays.sort 来比较我们的算法是否正确。代码实现对数器主要是使用对照来校验是否正确,除了一些比较方法、拷贝方法,这里需要重点理解一下 Math.random 方法,以及如何生成一个 [ -maxValue , maxValue ] 取值的整型数组。public class SortChecker { public static void main(Strin原创 2021-03-27 12:30:31 · 178 阅读 · 0 评论 -
排序算法——插入排序
一、算法思想给定一个无序数列,模拟一个指针从第0位开始向后,始终保持当前位置左边的数列是有序的。指针位置上的元素依次与前面的元素比较,当遇到小于自己的数或右边已经没有元素时,都停止比较,开始下一轮。生活中类比:扑克牌抓牌时,抓到的牌会从依次向左比较,并插入到左侧的有序数列中。二、代码演示public static void insertionSort(int[] arr) { if (arr == null || arr.length < 2) { r原创 2021-03-21 22:14:28 · 145 阅读 · 0 评论 -
排序算法——选择排序
一、算法思想给定一个无序数列,用第一个位置与后面的元素比较,只要遇到更小的,就将其调换。第一遍:用 idx 0 位置上的数与后面的数依次比较,更小则调换,否则不动第二遍:用 idx 1 位置上的数与后面的数依次比较,更小则调换,否则不动....二、代码实现选择排序中,每一遍都会有一个记录最小位置的变量,这个最小位置与遍数是同步的。for (int i = 0; i < arr.length - 1; i++) { int minIdx = i; fo.原创 2021-03-21 10:06:09 · 161 阅读 · 0 评论 -
哈希表的大小为何最好是素数
引言为什么散列函数采用取模运算?又为什么取模运算的被取模数最好是素数?素数是如何在取模运算中很好的规避冲突的?这些问题可能困扰诸多程序员很久了。我们总是说素数可以更好的避免冲突,但总是对各种长篇大论的分析望而却步。这篇文章是我在学习散列时针对素数在哈希函数中的如何成功避免大量冲突的原因总结。尽可能言简意赅地描述为什么素数那么香。一、结论素数能够在取模运算中避免冲突并不是一个数学定律,而且能够避免冲突也不是绝对的。从规律上来看,如果待存储的数列间隔是被取模数的因子,那么合数要比素数原创 2020-06-07 08:14:03 · 1807 阅读 · 0 评论 -
LeetCode(#1)————Two Sum
问题描述给定一个整数数组 nums和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。Given nums = [2, 7, 11, 15], target = 9,Because nums[0] + nums[1] = 2 + 7 = 9,return [...原创 2017-06-30 09:56:59 · 487 阅读 · 0 评论 -
LeetCode(#26)————删除排序数组中的重复项
题目给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。示例1:给定数组 nums = [1,1,2],函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。你不需要考虑数组中超出新长度后面的元素。...原创 2019-09-06 17:41:09 · 153 阅读 · 0 评论 -
LeetCode(#118)————杨辉三角形
问题描述给定一个非负整数numRows,生成杨辉三角的前numRows行。在杨辉三角中,每个数是它左上方和右上方的数的和。示例:输入: 5输出:[ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1]]实现方法class Solution { public List<List&...转载 2019-08-29 16:54:23 · 164 阅读 · 0 评论 -
排序算法——冒泡排序
冒泡排序简介冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料...原创 2018-09-09 18:32:09 · 410 阅读 · 0 评论 -
数据结构与算法————稀疏数组
引言数据压缩方面,我们往往可以通过稀疏数组来保存有效数据,节省存储空间。一、稀疏数组的概念当一个数组中大部分元素是0,或为同一个值的时候,可以使用稀疏数组来保存数组。它是一个十分有效的存储结构,便于节省存储空间。它的处理方式是:1、记录数组一共有几行几列,有多少不同的值;2、把具有不同值的元素的行、列及值记录在一个小规模二维数组中(稀疏数组),从而缩存储数据的规模。...原创 2019-08-06 22:55:40 · 729 阅读 · 0 评论 -
数据结构与算法————九九乘法表
问题描述通过Java语言实现九九乘法表的输出。使用一个for 循环和两个for循环。一个for循环public static void oneFor() { for (int i = 1, j = 1; i <= 9; j++) { System.out.print(j + "*" + i + "=" + i * j + "\t"); if (j == i) { ...原创 2019-08-29 17:10:23 · 1355 阅读 · 0 评论