数据结构与算法
数据结构与算法
玉树临风你卓哥
不积跬步,无以至千里;不积小流,无以成江海。
展开
-
数据结构 - 串(Sequence)
串是开发中非常熟悉的字符串,是由若干个字符组成的有限序列字符串thank的前缀(prefix)、真前缀(proper prefix)、后缀(suffix)、真后缀(proper suffix)串匹配算法查找一个模式串(Pattern)在文本串(Text)中的位置String text = "Hello world";String pattern = "or";text.in...原创 2020-02-03 17:42:49 · 1243 阅读 · 0 评论 -
数据结构 - B+树
B+树是B树的变体,常用于数据库和操作系统的文件系统中MySQL数据库的索引就是基于B+树实现的B+树的特点:分为内部节点(非叶子)、叶子节点2中节点内部节点只存储key,不存储具体数据叶子节点存储key和具体数据所有的叶子节点形成一条有序链表m阶B+树非根节点的元素数量x⌈m/2⌉ <= x <= m关于MySQL发音的官方说明https://dev.mys...原创 2020-02-02 13:48:30 · 716 阅读 · 0 评论 -
数据结构 - 跳表(Skip List)
思考一个有序链表搜索、添加、删除的平均时间复杂度是多少?O(n)能否利用二分搜索优化有序链表,将搜索、添加、删除的平均时间复杂度降低至O(logn)?链表没有像数组那样的高效随机访问(O(1)时间复杂度),所以不能像有序数组那样直接进行二分搜索优化那有没有其他办法让有序链表搜索、添加、删除的平均时间复杂度降低至O(logn)?使用跳表(SkipList)跳表,又叫做跳跃表、跳跃列...原创 2020-02-02 12:27:59 · 224 阅读 · 0 评论 -
数据结构 - 布隆过滤器(Bloom Filter)
思考如果要经常判断1个元素是否存在,你会怎么做?很容易想到使用哈希表(HashSet、HashMap),将元素作为key去查找时间复杂度:O(1),但是空间利用率不高,需要占用比较多的内存资源如果需要编写一个网络爬虫去爬10亿个网站数据,为了避免爬到重复的网站,如何判断某个网站是否爬过?很显然,HashSet、HashMap并不是非常好的选择是否存在时间复杂度低、占用内存较少的方案?...原创 2020-02-01 18:16:30 · 555 阅读 · 0 评论 -
算法 - 0-1背包问题
算法策略 : 动态规划(Dynamic Programming)有n件物品和一个最大承重为W的背包,每件物品的重量是w、价值是v在保证总重量不超过W的前提下,选择某些物品装入背包,背包的最大总价值是多少?注意:每个物品只有1件,也就是每个物品只能选择0件或者1件假设values是价值数组,weights是重量数组编号为k的物品,价值是values[k],重量是weights...原创 2020-01-31 19:13:12 · 426 阅读 · 0 评论 -
算法 - 最长公共子序列
算法策略 : 动态规划(Dynamic Programming)最长公共子串(Longest Common Substring)子串是连续的子序列求两个字符串的最长公共子串长度ABCBA和BABCA的最长公共子串是ABC,长度为3思路假设2个字符串分别是str1、str2i ∈ [1, str1.length]j ∈ [1, str2.length]假设dp...原创 2020-01-31 18:32:46 · 298 阅读 · 0 评论 -
算法策略 - 动态规划(Dynamic Programming)
动态规划,简称DP是求解最优化问题的一种常用策略通常的使用套路(一步一步优化)暴力递归(自顶向下,出现了重叠子问题)记忆化搜索(自顶向下)递推(自底向上)动态规划的常规步骤动态规划中的“动态”可以理解为是“会变化的状态”定义状态(状态是原问题、子问题的解)比如:定义dp(i)的含义设置初始状态(边界)比如设置dp(0)的值确定状态转移方程比如确定dp(i)和...原创 2020-01-29 18:22:44 · 332 阅读 · 0 评论 -
算法策略 - 分治(Divide And Conquer)
分治,也就是分而治之。它的一般步骤是将原问题分解成若干个规模较小的子问题(子问题和原问题的结构一样,只是规模不一样)子问题又不断分解成规模更小的子问题,直到不能再分解(知道可以轻易算出子问题的解)利用子问题的解推导出原问题的解因此,分治策略非常适合用递归需要注意的是:子问题之间是互相独立的分治的应用快速排序归并排序Karatsuba算法(大数乘法)...原创 2020-01-29 00:21:49 · 445 阅读 · 0 评论 -
算法策略 - 贪心(Greedy)
贪心策略,也称贪婪策略每一步都采取当前状态下最优的选择(局部最优解),从而希望推导出全局最优解贪心应用:哈夫曼树最小生成树算法:Prim、Kruskal最短路径算法:Dijkstra练习1 - 最优装载问题(加勒比海盗)在北美洲东南部,有一片神秘的海域,是海盗最活跃的加勒比海盗有一天,海盗们截获了一艘装满各种各样古董的货船,每一件古董都价值连城,一单打碎就失去了它的价值...原创 2020-01-28 19:33:20 · 1874 阅读 · 0 评论 -
算法策略 - 回溯(Back Tracking)
回溯可以理解为:通过选择不同的岔路口来通往目的地(找到想要的结果)每一步都选择一条路出发,能进则进,不能进则退回上一步(回溯),换一条路试试树、图的深度优先搜索(DFS)就是经典的回溯应用不难看出来,回溯很适合使用递归练习 - 八皇后问题(Eight Queens)八皇后问题是一个古老而著名的问题在8x8格的国际象棋上摆放八个皇后,使其不能互相攻击:任意两个皇后都不能处于同一行...原创 2020-01-27 17:18:01 · 1468 阅读 · 0 评论 -
数据结构与算法 --- 目录
数据结构 — 并查集数据结构 — 图算法 — 排序算法 — 递归原创 2020-01-22 11:31:26 · 220 阅读 · 0 评论 -
算法 - 汉若塔(Hanoi)
编程实现把A的n个盘子移动到C(盘子编号是[1, n])每次只能移动1个盘子大盘子只能放在小盘子下面1个盘子2个盘子3个盘子汉若塔 - 思路其实分2中情况讨论即可当 n == 1时,直接将盘子从A移动到C当 n > 1时,可以拆分成3大步骤将 n - 1个盘子从A移动到B将编号为n的盘子从A移动到C将 n - 1个盘子从B移动到C步骤1、3明...原创 2019-11-25 12:04:37 · 364 阅读 · 0 评论 -
算法 - 上楼梯(跳台阶)
楼梯有n阶台阶,上楼可以一步上1阶,也可以一步上2阶,走完n阶台阶共有多少种不同的走法?假设n阶台阶有f(n)种走法,第1步有2种走法如果上1阶,那就还剩n - 1阶,共f(n - 1)种走法如果上2阶,那就还剩n - 2阶,共f(n - 2)种走法所以f(n) = f(n - 1) + f(n - 2)int climbStairs(int n) { if (n ...原创 2019-11-25 12:03:22 · 4222 阅读 · 0 评论 -
算法 - 斐波那契数列
斐波那契额数列:1、1、2、3、5、8、13、21、34、…F(1)=1,F(2)=1,F(n)=F(n-1)+F(n-2) (n>=3)编写一个函数求第n项斐波那契数int fib(int n) { if (n <= 2) return 1; return fib(n - 1) + fib(n - 2);}根据递推式T(n) = T(n - 1) +...原创 2019-11-25 11:57:24 · 526 阅读 · 0 评论 -
算法策略 - 递归(Recursion)
递归:函数(方法)直接或间接调用自身。是一种常见的编程技巧int sum(int n) { if (n <= 1) return n; return n + sum(n - 1);}void a(int v) { if (v < 0) return; b(--v);}void b(int v) { a(--v);}递归现象...原创 2019-11-25 10:35:43 · 496 阅读 · 0 评论 -
数据结构 - 图(Graph)- 目录
图由顶点(vertex)和边(edge)组成,通常表示为G = (V, E)G标识一个图,V是顶点集,E是边集顶点集V有穷且非空任意两个顶点之间都可以用边来表示它们之间的关系,边集E可以是为空的图的应用举例图结构的应用极其广泛社交网络地图游戏开发…有向图(Directed Graph)有向图的边是有明确方向的有向无环图(Directed Acycl...原创 2019-11-14 17:06:58 · 1462 阅读 · 0 评论 -
算法 - 图(Graph)- 最短路径(Shortest Path)- Floyd(弗洛伊德算法)
图(Graph) 图(Graph)- 最短路径(Shortest Path)FloydFloyd属于多源最短路径算法,能够求出任意2个顶点之间的最短路径,支持负权边时间复杂度:O(V³),效率比执行V次Dijkstra算法要好(V是顶点数量)算法原理从任意顶点i到任意顶点j的最短路径不外乎两种可能直接从 i 到 j从i经过若干个顶点到j假设 dist(i,...原创 2019-11-14 18:13:30 · 1033 阅读 · 0 评论 -
算法 - 图(Graph)- 最短路径(Shortest Path)- Bellman-Ford(贝尔曼-福特算法)
图(Graph) 图(Graph)- 最短路径(Shortest Path)Bellman - FordBellman-Ford 也属于单源最短路径算法,支持负权边,还能检测出是否有负权环算法原理:对所有的边进行V - 1次松弛操作(V是节点数量),得到所有可能的最短路径时间复杂度:O(EV),E是变数,V是节点数量下图的最好情况是恰好从做导游的顺序对边进行松弛操作对...原创 2019-11-14 18:09:52 · 1362 阅读 · 0 评论 -
算法 - 图(Graph)- 最短路径(Shortest Path)- Dijkstra(迪杰斯特拉算法)
图(Graph) 图(Graph)- 最短路径(Shortest Path)DijkstraDijkstra属于单源路径最短路径算法,用于计算一个顶点到其他所有顶点的最短路径适用前提:不能有负权边时间复杂度:可优化至O(ELogV),E是边数量,V是节点数量由荷兰的科学家Edsger Wybe Dijkstra发明,曾在1972年获得图灵奖Dijkstra - 等...原创 2019-11-14 17:58:41 · 1942 阅读 · 0 评论 -
算法 - 图(Graph)- 最短路径(Shortest Path)
图(Graph)最短路径(Shortest Path)最短路径是指两顶点之间权值之和最小的路径(有向图、无向图均适用,不能有负权环)最短路径 - 无权图无权图相当于全部边权值为1的有权图最短路径 - 负权边有负权边,但没有负权环时,存在最短路径A到E的最短路径是:A->B->E最短路径 - 负权环有负权环时,不存在最短路径最短路径...原创 2019-11-14 17:53:30 · 2847 阅读 · 0 评论 -
算法 - 图(Graph)- 生成树(Spanning Tree)- Kruskal算法
Kruskal算法 - 执行过程按照边的权重顺序(从小到大)将边加入生成树中,知道生成树中含有V - 1条边位置(V是顶点数量)若加入该边会与生成树形成环,则不加入该边从第3条边开始,可能会与生成树形成环Kruskal算法 - 实现private Set<EdgeInfo<V, E>> kruskal() { int edgeSize = ver...原创 2019-11-14 17:38:16 · 1185 阅读 · 0 评论 -
算法 - 图(Graph)- 生成树(Spanning Tree)- Prim算法
切分定理切分(Cut):把图中的节点分为两部分,成为一个切分下图有个切分C = (S, T),S = {A, B, D},T = {C, E}横切边(Crossing Edge):如果一个边的两个顶点,分别属于切分的两部分,这个边称为横切边比如上图的边BC、BE、DE就是横切边切分定理:给定任意切分,横切边中权值最小的边必然属于最小生成树Prim算法 - 执行过程假设G = ...原创 2019-11-14 17:35:01 · 1655 阅读 · 1 评论 -
算法 - 图(Graph)- 生成树(Spanning Tree)
生成树(Spanning Tree),也称为支撑树连通图的极小连通子图,它含有图中全部的n个顶点,恰好只有n-1条边最小生成树(Minimum Spanning Tree)最小生成树(Minimum Spanning Tree,简称MST)也称为最小权重生成树(Minimum Weigth Spanning Tree)、最小支撑树是所有生成树中,总权值最小的那棵适用于有权的连通...原创 2019-11-14 17:29:32 · 5832 阅读 · 1 评论 -
算法 - 图(Graph)- AOV网(Activity On Vertex Nework)- 拓扑排序(Topological Sort)
AOV网(Activity On Vertex Nework)一项大的工程常被分为多个小的子工程子工程之间可能存在一定的先后顺序,即某些子工程必须在其他的一些子工程完成后才能开始在现代化管理中,人们常用用向图来描述和分析一项工程的计划和实施过程,子工程被称为活动(Activity)以顶点为活动、有向边表示活动之间的先后关系,这样的图简称为AOV网标准的AOV网必须是一个有向无环图(Di...原创 2019-11-14 17:20:54 · 417 阅读 · 0 评论 -
算法 - 图(Graph)- 遍历
图的遍历从图中某一顶点出发访问图中其余顶点,且每一个顶点仅被访问一次图有2种常见的遍历方式(有向图、无向图都适用)广度优先搜索(Breadth First Search,BFS),又称为宽度优先搜索、横向优先搜索深度优先搜索(Depth First Search,DFS)发明"深度优先搜索"算法的2位科学家在1986年共同获得计算机领域的最高奖:图灵奖广度优先搜索(Brea...原创 2019-11-14 17:10:45 · 652 阅读 · 0 评论 -
数据结构 - 并查集(Union Find)
需求分析假设有n个村庄,有些村庄之间有连接的路,有些村庄之间并没有连接的路设计一个数据结构,能快速执行2个操作查询2个村庄之间是否有连接的路连接2个村庄数组、链表、平衡二叉树、集合(Set)?查询、链接的时间复杂度都是:O(n)并查集能够办到查询、链接的均摊时间复杂度都是O(α(n)),α(n)<5并查集非常适合解决这类“连接”相关的问题并查集(Union F...原创 2019-11-07 15:08:14 · 412 阅读 · 0 评论 -
算法 - 桶排序(Bucket Sort)
执行流程:创建一定数量的桶(比如用数组、链表作为桶)按照一定的规制(不同类型的数据,规则不同),将序列中的元素均匀分配到对应的桶分别对每个桶进行单独排序将所有非空桶的元素合并成有序序列元素在同种的索引元素值*元素数量实现double[] array = {0.34, 0.47, 0.29, 0.84, 0.45, 0.38, 0.35, 0.76}// 桶数组L...原创 2019-10-29 13:10:42 · 273 阅读 · 0 评论 -
算法 - 基数排序(Radix Sort)
基数排序非常适合用于整数排序(尤其是非负整数),因此只演示对非负整数进行基数排序执行流程:一次对个位数、十位数、百位数、千位数、万位数…进行排序(从低位到高位)个位数、十位数、百位数的取值范围都是固定的0~9,可以使用计数排序对它们进行排序思考:如果先对高位排序,再对地位排序,是否可行?不行实现private void countingSort(int divider, int[]...原创 2019-10-29 13:07:56 · 1677 阅读 · 0 评论 -
算法 - 计数排序(Counting Sort)
之前学习的冒泡、选择、插入、归并、快速、希尔、堆排序,都是基于比较的排序平均时间复杂度目前最低是O(nlogn)计数排序、桶排序、基数排序,都不是基于比较的排序它们是典型的用空间换时间,在某些时候,平均时间复杂度可以比O(nlogn)更低计数排序于1954年由Harold H.Seward提出,适合对一定范围内的整数进行排序计数排序的核心思想统计每个整数在序列中出现的次数,进而推导出...原创 2019-10-29 13:04:53 · 215 阅读 · 0 评论 -
算法 - 希尔排序(Shell Sort)
1959年由唐纳德·希尔(Donald Shell)提出希尔排序把序列看作是一个矩阵,分成m列,逐列进行排序m从某个整数逐渐减为1当m为1时,整个序列将完全有序因此,希尔排序也被称为逐渐增量排序(Diminashing Increment Sort)矩阵的列数取决于补偿序列(step sequence)比如,如果步长序列为{1,5,19,41,109,…},就代表依次分层...原创 2019-10-29 12:57:28 · 185 阅读 · 0 评论 -
算法 - 快速排序(Quick Sort)
1960年由查尔斯·安东尼·理查德·霍尔(Charles Antony Richard Hoare,缩写为C.A.R.H)昵称为东尼·霍尔(Tony Hoare )执行流程:从序列中选择一个轴点元素(pivot)假设每次选择0位置的元素为轴点元素利用pivot将序列分割成2个子序列将小于pivot的元素放在pivot前面(左侧)将大于pivot的元素放在pivot后面(右侧)...原创 2019-10-28 19:12:47 · 180 阅读 · 0 评论 -
算法 - 归并排序(Merge Sort)
1954年由约翰·冯·冯诺依曼(John von Nenumann)首次提出执行流程不断地将当前序列平均分割成2个子序列(直到不能分割(序列中只有1个元素))不断地将2个子序列合并成一个有序序列(直到最终只剩下1个有序序列)归并排序 - divide实现// 对 [begin, end) 范围的数据进行归并排序private void sort(int begin, int...原创 2019-10-25 13:52:00 · 199 阅读 · 0 评论 -
算法 - 插入排序(Insertion Sort)
插入排序非常类似于扑克牌的排序执行流程在执行过程中,插入排序会将序列分为2部分(头部是已经排好序的,尾部是待排序的)从头开始扫描每一个元素(每当扫描到一个元素,就将它插入到头部适合的位置,使得头部数据依然保持有序)void sort() { for (int begin = 1; begin < array.length; begin++) { int...原创 2019-10-24 12:57:44 · 146 阅读 · 0 评论 -
算法 - 堆排序(Heap Sort)
堆排序可以认为是对选择排序的一种优化执行流程对序列进行原地建堆(heapify)重复执行以下操作,直到堆的元素数量为1(交换堆顶元素与尾元素,对的元素数量减1,对0位置进行1次siftDown操作)最好、最坏、平均时间复杂度O(nlogn),空间复杂度:O(1),属于不稳定排序void sort() { // 原地建堆 ...原创 2019-10-22 13:31:03 · 212 阅读 · 0 评论 -
算法 - 选择排序(Selection Sort)
执行流程从序列中找到最大的那个元素,然后与最末尾的元素交换位置(执行完一轮后,最末尾的那个元素就是最大的元素)忽略1中曾经找到的最大元素,重复执行步骤1选择排序的交换次数要远远小于冒泡排序,平局性能优于冒泡排序最好、最坏、平均时间复杂度:O(n²),空间复杂度O(1),属于稳定排序 for (int end = array.lengt...原创 2019-10-22 13:27:52 · 182 阅读 · 0 评论 -
算法 - 冒泡排序(Bubble Sort)
平均时间复杂度:O(n²),最好情况:O(n),最坏情况O(n²)空间复杂度:O(1)常规冒泡排序for (int end = array.length - 1; end > 0; end--) { for (int begin = 1; begin <= end; begin++) { // if (ar...原创 2019-10-22 11:57:31 · 187 阅读 · 0 评论 -
算法 --- 十大排序
排序算法的稳定性(Stability)如果相等的2个元素,在排序前后的相对位置保持不变,那么这是稳定的排序算法对自定义对象进行排序是,稳定性会影响最终的排序效果冒泡排序属于稳定的排序算法稍有不慎,稳定你的排序算法也可能被写成不稳定的排序算法原地算法(In-place Algorithm)原地算法(In-place Algorithm)不依赖额外的资源或者依赖少数的额外资源,仅...原创 2019-10-22 12:12:01 · 226 阅读 · 0 评论