数据结构和算法
1. 排序算法
2. 数据结构
3. 高级设计和分析技术
4. 练习题
阿飞__
熟悉 Android、C++ 等
展开
-
有权最短路径问题:贝文曼福德(Bellman Ford)算法 & Java 实现
一、贝尔曼福德算法1. 简介贝尔曼福德(Bellman Ford)算法也是求解单源最短路径问题,相比狄克斯特拉(dijkstra)算法,它运行效率会差一些,但是它可以处理边的权重为负值的情况,而狄克斯特拉算法要求变的权重不能为负数。备注:狄克斯特拉算法,可以戳这个链接:https://blog.csdn.net/afei__/article/details/833522052. 算法思想...原创 2018-10-25 13:54:17 · 2193 阅读 · 0 评论 -
有权最短路径问题:狄克斯特拉(Dijkstra)算法 & Java 实现
一、有权图之前我们知道,在无权重的图中,求两个顶点之间的最短路径,可以使用 广度优先搜索 算法。但是,当边存在权重(也可以理解为路程的长度)时,广度优先搜索不再适用。针对有权图中的两点间最短路径,目前主要有 狄克斯特拉算法 和 贝尔曼福德算法 两种解决方法。本博客以狄克斯特拉算法为例。备注:广度优先搜索不了解的,可以戳这个链接:https://blog.csdn.net/afei__/ar...原创 2018-10-24 22:37:12 · 4846 阅读 · 2 评论 -
最小生成树问题:算法分析 & Java 实现
一、简介1. 什么是最小生成树将一个有权图中的所以顶点都连接起来,并保证连接的边的总权重最小,即最小生成树(mini spanning tree)问题。例如,电子电路设计中,将所有组件的针脚连接在一起,且希望所使用的连线长度最短。2. 图示如上图(这里借用的是《算法导论》一书中的图)所示,每条边上的数字表示权重。我们使用阴影边连接了所有的顶点,并保证了其总权重是最小的。注意最小生成树...原创 2018-10-23 22:22:37 · 7193 阅读 · 4 评论 -
Java 希尔排序
一、简介希尔排序名称源于它的发明者 Donald Shell,又称缩小增量排序。本质上讲,希尔排序是直接插入排序的一种改进,减少了复制次数,提升了速度。其原理为选定一个增量 increment,使得数组中间隔为 increment 的元素放在一个子序列中,对每个子序列进行插入排序。然后逐渐缩小 increment,重复上述划分和排序,直至 increment 缩小到 1 时完成排序。二、图解...原创 2018-10-21 20:10:16 · 395 阅读 · 0 评论 -
无权重最短路径问题:广度优先搜索 & Java 实现
一、什么是图通俗的说,图就是由 顶点(Vertex) 和 边(edge) 组成的。一般来说又分为 有向图 和 无向图,即顶点到顶点的边是否是有方向区分的。二、广度优先搜索1. 概念广度优先搜索(Breadth First Search)通常用于指出是否存在一条路径由顶点 A 到达顶点 B,如果有,则找出顶点 A 到顶点 B 的最短路径。注意,这里的最短路径是没有权重概念的,即可以认为任一...原创 2018-10-21 16:20:49 · 2419 阅读 · 2 评论 -
动态规划:最长回文子串 & 最长回文子序列
一、题目所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如 “a”、“aba”、“abba”。对于一个字符串,其子串是指连续的一段子字符串,而子序列是可以非连续的一段子字符串。最长回文子串 和 最长回文子序列(Longest Palindromic Subsequence)是指任意一个字符串,它说包含的长度最长的回文子串和回文子序列。例如:字符串 “ABCDDCEFA...原创 2018-10-20 15:51:49 · 26335 阅读 · 5 评论 -
动态规划:最长公共子串 & 最长公共子序列
一、最长公共子串1. 题目给定两个序列 X 和 Y,如果 Z 即是 X 的子串,又是 Y 的子串,我们就称它是 X 和 Y 的公共子串,注意子串是连续的。例如 X = { A, B, C, D, E, F, G },Y = { A, B, Z, D, E, F, K, G },那么它们最长的公共子串即 { D, E, F }2. 思路借助一下《图解算法》中的例子。假设对于两个字符串 fi...原创 2018-10-18 21:31:08 · 12079 阅读 · 3 评论 -
二分查找
原理简介 针对一个有序数组(假设为升序),要查找某个 item 是否存在,并返回 item 的索引 index,则可以使用二分查找法。 比如存在100个有序元素,简单查找就是遍历这100个元素,找到和 item 相等的元素就返回,这样我们最多可能需要查找100次;而二分查找,即我先拿到中间这个元素,判断大于还是小于 item,然后根据结果可以缩小一半的查找区间,...原创 2018-05-01 16:27:28 · 272 阅读 · 0 评论 -
交换两个值的三种方法,详细分析
开发中我们经常会需要交换两个值,常见有几种方式:备注:交换前可以先判断两个数是否相等,相等的话就可以跳过交换过程了。方式一:int a = 3;int b = 4;// swapint temp = a;a = b;b = temp;这种方式是最直接也是最容易让你理解的方式了(为了代码的易读性,还是推荐使用这种形式),不过有一个临时变量temp,如果你不想创建临时变...原创 2018-05-01 18:57:40 · 7738 阅读 · 0 评论 -
Java 选择排序法
原理简介 选择排序原理即是,遍历元素找到一个最小(或最大)的元素,把它放在第一个位置,然后再在剩余元素中找到最小(或最大)的元素,把它放在第二个位置,依次下去,完成排序。时间复杂度 选择排序的时间复杂度为 O(n^2)。 第一次需要检查n个元素,但随后检查的元素数依次为n - 1, n – 2, …, 2和1。平均每次检查的元素数为1/2 ...原创 2018-05-01 20:43:12 · 43648 阅读 · 2 评论 -
Java 快速排序法
原理简介 快速排序原理即是,选择数组中的一个元素作为基准值 pivot(通常使用第一个就行),然后遍历其他元素,将小于 pivot 的元素放置在左边,将大于 pivot 的元素放置在右边。如是你可以得到两个子数组,再依次对子数组进行快速排序,最终完成排序。时间复杂度 快速排序比选择排序快得多,其时间复杂度为 O(n * lg n),是最快的排序算法之一。最糟糕...原创 2018-05-05 16:06:32 · 2926 阅读 · 0 评论 -
Java 求最大公约数(欧几里德算法证明)
基本概念如果数a能被数b整除,a就叫做b的倍数,b就叫做a的约数。几个整数中公有的约数,叫做这几个数的公约数;其中最大的一个,叫做这几个数的最大公约数(greatest common divisor)。 代码示例1.使用循环public static int getGCD(int a, int b) { if (a < 0 || b < 0) { ...原创 2018-05-06 17:29:45 · 9515 阅读 · 0 评论 -
判断一个数是不是质数(素数),3种方式介绍
一、概念介绍 大家中学都学过,就不过多介绍了,大致提两点: 质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。 0和1既不是质数也不是合数,最小的质数是2二、方法介绍1.最直观,但效率最低的写法public static boolean isPrime(int n){ if (n <= ...原创 2018-06-10 09:56:59 · 288584 阅读 · 51 评论 -
数据结构和算法基础概念介绍
一、什么是算法算法是指一系列解决问题的清晰指令。 二、算法特征有穷性:算法必须能够在执行有限个步骤之后终止 确切性:算法的每一步都必须要有确切的定义 输入项:算法必须有0个或多个输入,描述算法执行的初始状态。0个输入即算法本身已经拥有了初始条件 输出项:算法必须要有一个或者多个输出,反应算法加工后的结果,没有输出的算法是没有意义的 可行性:算法的每个操作都是可以在有限时间内...原创 2018-10-05 16:11:34 · 577 阅读 · 0 评论 -
经典冒泡排序法 & 冒泡排序法的优化
一、原理简介冒泡排序的原理即是,对于一个元素个数为 n 的无序集合,从第一个元素开始依次和下一个元素比较,较大者放在后面的位置,最终可以得到一个最大值并放置在最后一个位置。接下来再遍历 0 至 n-1 个元素,找到第二大的数放置在 n-1 的位置,反复如此完成排序。 二、时间复杂度冒泡排序的时间复杂度为 O(n^2)。第一次需要检查n个元素,但随后检查的元素数依次为n - 1,...原创 2018-10-05 16:30:14 · 1051 阅读 · 0 评论 -
Java 插入排序法
一、原理简介插入排序的原理即是,从第二个元素开始,找到合适的位置,将元素插入到之前已排好序的元素中去,依次下去最终完成排序。就类似打扑克牌,每次抓到一张新的牌时,都将其插入到手中已排好序的牌组中。插入排序适用于少量数据的排序,特别是将一个新的元素插入到已有的排好序的数组中,插入排序是一种稳定的排序方法。 二、时间复杂度插入排序的时间复杂度为 O(n^2)。由于每次插入一个新...原创 2018-10-06 09:40:46 · 1318 阅读 · 0 评论 -
求最大连续子序列的和,时间复杂度为 O(n)
练习题目给定数组 [ a0, a1, a2, …, an ] ,找出其最大连续子序列和,要求时间复杂度为 O(n),数组包含负数。例如:输入 [ -2,11,-4,13,-5,-2] ,输出 20(即 11 到 13)。 解答关于这个问题有很多种解法,这里介绍一种时间复杂度仅为 O(n) 的解法,即只需要一次循环即可。代码:public class Main { ...原创 2018-10-06 11:55:24 · 3223 阅读 · 3 评论 -
Java 归并排序法
一、原理简介归并排序又称合并排序,即针对两个已经排序好的数组,将其合并为一个排序数组。归并过程中,依次比较两个数组中的元素,将较小值(假设为升序排序)放入新数组中,最终遍历完两个数组后完成排序。归并排序是一种速度较快的排序方法。 二、时间复杂度当我们合并 两个已排序的数组,只需要遍历一遍即可,其时间复杂度为 O(n)。当我们对一个 无序数组 使用归并排序法进行排序,我们可以...原创 2018-10-06 13:10:52 · 459 阅读 · 0 评论 -
求数组中逆序对的数量,时间复杂度 O(n * lg n)
题目这是《算法导论 第3版》第二章的第 4 个思考题。原题为:假设 A[ 1…n ] 是一个有 n 个不同数的数组。若 i < j 且 A[ i ] > A [ j ] ,则对偶 (i, j) 称为 A 的一个逆序对。给出一个确定在 n 个元素的任何排列中逆序对数量的算法,时间复杂度 O(n * lg n)。(提示:修改归并排序) 分析首先有一种直观的...原创 2018-10-06 16:44:20 · 4132 阅读 · 0 评论 -
堆排序法(Java & C/C++ 实现)
一、前言堆排序是利用堆这种数据结构而设计的一种排序算法。时间复杂度为 O(n * lg n)。介绍堆排序前,我们先介绍一下堆的相关概念,如果你对堆的概念还不熟悉的话可以看看。 二、堆1. 示意图2. 性质除最底层外,该树是完全充满的,且是从左到右填充。树的根结点是 A[ 1 ],若某一结点下标为 i,则很容易得到它的父节点为 i/2,左子结点为 2i,右子结点为...原创 2018-10-07 15:27:39 · 389 阅读 · 0 评论 -
计数排序:时间复杂度仅为 O(n) 的排序算法
一、简介计算排序假设 n 个输入元素都是 0 到 k 区间内的一个整数,其中 k 为某个整数。基本原理:创建一个长度为 k+1 的数组 count[],它的 count[i] 的值对应输入数组中 i 出现的次数。通过遍历一次输入数组并统计每个元素出现次数,最后遍历 count[] 输出。 二、时间复杂度计算排序的时间复杂度为 O(n)。计算排序不是比较排序算法,它没有元...原创 2018-10-07 18:40:10 · 6447 阅读 · 0 评论 -
Java 桶排序,详细分析
一、简介桶排序也是时间复杂度仅为 O(n) 的一种排序方法,它假设输入数据服从均匀分布,我们将数据分别放入到 n 个桶内,先对桶内数据进行排序,然后遍历桶依次取出桶中的元素即可完成排序。和计数排序类似,桶排序也对输入数据作了某种假设,因此它的速度也很快。具体来说,计数排序假设了输入数据都属于一个小区间内的整数,而桶排序则假设输入数据是均匀分布的,即落入每个桶中的元素数量理论也是差不多的,...原创 2018-10-08 11:42:17 · 13286 阅读 · 15 评论 -
Java 基数排序
一、简介基数排序是这样一种排序算法,我们可以从低位(个位)开始,根据个位数排序一次,然后根据十位数排序,再根据百位数进行排序……最终完成整个数组的排序。对于十进制数字而言,每一位只会是 0~9 这十个数字,我们通常使用桶排序(计数排序)来完成每一位数的排序。桶排序是一种稳定的排序算法,基数排序的正确性依赖一种稳定的排序算法。基数排序其实是分 LSD(从低位向高位排序) 和 MSD(从...原创 2018-10-08 17:46:45 · 2340 阅读 · 0 评论 -
使用基数排序实现英文单词字母表顺序排序,时间复杂度 O(n)
一、题目英文单词由 26 个字母组成,现要求设计一个算法,对一组乱序单词实现字母表顺序排序。二、思路和分析算法的选择有很多,这里我们选择使用 基数排序,这是一种时间复杂度为 O(n) 的排序算法,关于它的介绍,也可以参考我的这一篇博文:https://blog.csdn.net/afei__/article/details/82971310不考虑大小写的话,我们需要准备 26...原创 2018-10-08 18:11:31 · 3053 阅读 · 0 评论 -
二叉树的先序遍历、中序遍历、后序遍历:递归 & 循环 两种实现
一、预备知识首先你得了解 树 的基本概念,二叉树是每个结点至多只有两个子结点的树,常称之为左右结点。二叉树的遍历方式有 先序遍历(preorder traeversal)、中序遍历(inorder traversal)、后序遍历(postorder traversal) 三种,假设结点为 N,左子结点为 L,右子结点为 R。则:先序遍历:NLR(N 在最前面) 中序遍历:LNR(N ...原创 2018-10-10 21:00:24 · 20167 阅读 · 1 评论 -
散列函数中求模运算为什么要使用素数,原因分析
一、散列函数散列函数即是将元素映射到对应槽位置的方法。一个好的散列函数应该是尽可能的将元素均匀的散列到 m 个槽位中的一个。 二、除法散列法散列函数的实现有很多种,其中一种常见的散列函数即 除法散列法,h(k) = k mod m,通过取 k 除以 m 的余数,将关键字 k 映射到 m 个槽上。由于只需做一次除法操作,所以除法散列法是非常快的。当我们使用除法散列法时,m 的...原创 2018-10-11 13:14:26 · 4215 阅读 · 3 评论 -
用 Java 手把手写一个“二叉搜索树”,支持泛型
一、二叉搜索树先说一下二叉树,二叉树是一种至多只有左右两个子结点的树形结构。二叉搜索树是二叉树的一种,对于任意一个结点 x,其左子树的任一结点的值都不大于 x 的值,其右子树的任一结点的值都不小于 x 的值。二叉搜索树上的基本操作有 查询 (search)、最小值 (minimum)、最大值 (maximum)、前驱值 (predecessor)、后继值 (successor)、插入 ...原创 2018-10-13 14:39:24 · 5112 阅读 · 5 评论 -
(兔子繁殖问题)斐波那契数列:递归&非递归解法
题目假设一对幼年兔子需要一个月长成成年兔子,一对成年兔子一个月后每个月都可以繁衍出一对新的幼年兔子。不考虑死亡的情况,问第 N 个月时共有多少对兔子?这是一个典型的斐波那契数列问题,即第一个月有一对兔子;第二个月兔子长大了,但还是只有一对兔子;第三个月多了一对幼年兔子,共有两对兔子了;第四个月又生了一对幼年兔子,同时第三个月的幼年兔子长成了成年兔子;……那么兔子数量...原创 2018-10-16 13:52:03 · 11564 阅读 · 3 评论 -
求海量数据中第 K 位元素 & 求 top K 的数据,各解决方法示例和总结
一、题目在一个由 n 个元素组成的集合中,按从小到大顺序排序的话,第 K 个顺序统计位即指第 K 个数,当 K = n 时即最大值,当 K = 1 时即最小值。先给定一个无序的元素集合,求集合中第 K 统计位的值是多少?同理,若求 top K 的数据的话,即求集合中最大的前 K 个数分别是多少?例如,给定数组 [ 0, 9, 3, 6, 8, 2, 1, 5, 7, 4 ] ,则第 4...原创 2018-10-17 21:44:40 · 946 阅读 · 0 评论 -
动态规划:钢条切割问题
一、题目钢条切割问题 是《算法导论》一书中介绍动态规划时的一道引题。即:某公司购买长钢条,将其切割为短钢条出售。假设切割工序没有成本支出,已知长度为 i 的钢条出售价格为 pi ,钢条长度均为整数,公司管理希望知道最佳的切割方案。价格表样例:长度i12345678910价格pi1589101717202430现给定长钢条的长度...原创 2018-10-18 15:56:28 · 3509 阅读 · 0 评论