All Projects → Ethanzjp → Algorithms

Ethanzjp / Algorithms

Licence: GPL-3.0 license
Algorithms competition, Leetcode solutions, deep learning algorithms, parallel computing, and SQL solutions.

Programming Languages

C++
36643 projects - #6 most used programming language
Jupyter Notebook
11667 projects
Cuda
1817 projects
python
139335 projects - #7 most used programming language
c
50402 projects - #5 most used programming language
go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to Algorithms

.codebits
📚 List of resources for Algorithms and Data Structures in Python & other CS topics @2017
Stars: ✭ 144 (+242.86%)
Mutual labels:  leetcode, databases
chainDB
A noSQL database based on blockchain technology
Stars: ✭ 13 (-69.05%)
Mutual labels:  databases
Competitive-programing
This repository is for encouraging people in competitive programming. And making PR's on a regular basis. Through this repo, Geeks can find solutions for various programming problems and also give your code to increase the repo.
Stars: ✭ 20 (-52.38%)
Mutual labels:  leetcode
LearnCPP
Learn Cpp from Beginner to Advanced ✅ Practice 🎯 Code 💻 Repeat 🔁 One step solution for c++ beginners and cp enthusiasts.
Stars: ✭ 359 (+754.76%)
Mutual labels:  leetcode
FAANG-Coding-Interview-Questions
A curated List of Coding Questions Asked in FAANG Interviews
Stars: ✭ 1,195 (+2745.24%)
Mutual labels:  leetcode
linghu-algorithm-templete
算法面试必备,推荐刷题网站www.lintcode.com。北大学霸的《LeetCode刷题模板》+V领取: jiuzhangfeifei
Stars: ✭ 2,680 (+6280.95%)
Mutual labels:  leetcode
code-exercise
Personal algorithm practice
Stars: ✭ 32 (-23.81%)
Mutual labels:  leetcode
LeetCode-Book
《剑指 Offer》 Python, Java, C++ 解题代码,LeetBook《图解算法数据结构》配套代码仓。
Stars: ✭ 1,164 (+2671.43%)
Mutual labels:  leetcode
datajoint-python
Relational data pipelines for the science lab
Stars: ✭ 140 (+233.33%)
Mutual labels:  databases
LeetCode-Solution-Well-Explained
My LeetCode solutions using Java. Sorted in different topics and add detailed comments for easy understanding.
Stars: ✭ 23 (-45.24%)
Mutual labels:  leetcode
js-algorithm
A personal algorithm problems collection about Data Structures and Leetcode questions. It contains all Q&A on labuladong website.个人Javascript, Typescript版 数据结构与算法的训练集.它包括了Js数据结构,剑指Offer的全部题目,以及labuladong网站的所有算法题和总结,配合labuladong网站内容练习食用效果更佳。持续更新中...
Stars: ✭ 26 (-38.1%)
Mutual labels:  leetcode
algorithm
acwing, leetcode, kickstart, 算法模板, PAT 等等
Stars: ✭ 162 (+285.71%)
Mutual labels:  leetcode
data-structure algorithm
🐎JavaScript数据结构和算法
Stars: ✭ 48 (+14.29%)
Mutual labels:  leetcode
leetcode-js
LeetCode JavaScript solutions
Stars: ✭ 16 (-61.9%)
Mutual labels:  leetcode
leetcode-summary-python
The summary for LeetCode questions
Stars: ✭ 20 (-52.38%)
Mutual labels:  leetcode
Leetcoding-Challenge
This repository contains Leetcode Challenge Submissions.
Stars: ✭ 26 (-38.1%)
Mutual labels:  leetcode
coding-for-food
Coding for food
Stars: ✭ 19 (-54.76%)
Mutual labels:  leetcode
dsa-roadmaps
DSA roadmaps and their solutions
Stars: ✭ 20 (-52.38%)
Mutual labels:  leetcode
CodeTest
some source code for some online judge
Stars: ✭ 40 (-4.76%)
Mutual labels:  leetcode
leet-code
LeetCode's competitive programming questions solution repository
Stars: ✭ 18 (-57.14%)
Mutual labels:  leetcode

数据结构与算法

Github stars github language

1. 概述

包括但不限于以下内容:

2. 算法列表

最短路径类型 算法 时间复杂度 算法类型
边权均为正,单源最短路径,稠密图 朴素dijkstra O(n^2) 贪心
边权均为正,单源最短路径,稀疏图 heap+dijkstra O(mlogn) 贪心
边权存在负值,单源最短路径,限制最短路径<=k bellman-ford O(nm) 离散数学、动态规划
边权存在负值,单源最短路径, 不限制 SPFA 平均情况下为O(m),最坏O(nm) BFS优化bellman-ford
多源(起点)汇(终点)最短路径 floyd O(n^3) 动态规划
最小生成树类型 算法 时间复杂度 算法类型
稠密图 朴素prim O(n^2) 贪心
稀疏图 heap+prim O(mlogn) 贪心
稀疏图 kruskal O(mlogm) 贪心

注意:如果点数n和边数m在同一个数量级为稀疏图,如果m和n^2在一个数量级,则该图为稠密图。

3. 算法设计技术

method extra space priorities Data Structure
DFS O(h) stack
BFS O(2^h) shortest path(权重必须为1,否则不能找到最短路径)、topology sort queue

4. 时空复杂度分析

4.1 理论

 int cal(int n) {
   int sum = 0;
   int i = 1;
   for (; i <= n; ++i) {
     sum = sum + i;
   }
   return sum;
 }

如上述代码,在上述代码中,只有for循环中的sum+=i被执行了n次,其它代码的执行均与n无关。本例中,我们将算法的时间复杂度表示为O(n),表示算法的执行时间与n成线性比例。在算法分析中,用大O表示时间复杂度,大O不是算法的真正执行时间,而是表示代码的执行时间随数据规模增长的变化趋势,所有我们也称为渐进时间复杂度。常见的时间复杂度包括:

$O(1) &lt; O(lgn) &lt; O(n) &lt; O(nlogn) &lt; O(n^2) &lt; O(2^n) &lt; O(n!)$ 其中,$O(2^n) < O(n!)$ 被称为$NP$难问题。为使得公式能够真长显示,请在chrome的扩展程序中,打开chrome网上应用店,然后搜索MathJax Plugin for Github,下载该插件,并且启用,就可以让上述公式正常显示。

在时空复杂度分析中,有下面三个法则:

  • 只关注循环执行次数最多的一段代码
  • 加法法则:总复杂度等于量级最大的那段代码的复杂度,该法则适用于多段平行代码段,总的时间复杂度为最大
  • 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

4.2 最好,最坏、平均、时间复杂度分析

3.1节讲了基本的时间复杂度表示方法,本节将重点讲述最好、最坏、平均、均摊时间复杂度分析,这样便有了完整的时间复杂度分析方法。

// n 表示数组 array 的长度
int find(int[] array, int n, int x) {
  int i = 0;
  int pos = -1;
  for (; i < n; ++i) {
    if (array[i] == x) pos = i;
  }
  return pos;
}

上述代码的时间复杂度为O(n),代码性能较差,修改为下面部分:

// n 表示数组 array 的长度
int find(int[] array, int n, int x) {
  int i = 0;
  int pos = -1;
  for (; i < n; ++i) {
    if (array[i] == x) {
       pos = i;
       break;
    }
  }
  return pos;
}

如上代码,在**最好情况下:数组的首元素的值与x相等,此时时间复杂度为O(1),在最坏情况下:遍历整个数组,但是仍然没有找到对应的元素,此时的时间复杂度为O(n)。**至于平均时间复杂度的分析稍微复杂一些,**平均之间复杂度又称为期望时间复杂度或加权时间复杂度。**在本例中,有n个元素,每个元素都有$1/n$的可能性被选中,并且被选中的元素有$1/2$的可能性等于x,因此:

$1 * 1/(2n) + 2 * 1/(2n) + ... + n * 1/(2n) + n * 1/2= (3n+1)/4$

上述值就是每个位置可能出现等于x的情况的加权平均值,也叫做期望值,所以平均时间复杂度的全称应该叫做加权平均时间复杂度或者期望时间复杂度。上述值用大O表示为O(n)。另外一种分析方法是,总共有n+1种情况,n种情况下找到该元素,1种情况下元素不在数组中,如下:

$(1+2+...+n+n)/(n+1) = n(n+3)/(2(n+1))$

这种分析方法没有考虑每种情况出现的概率,不可取。

4.3 均摊时间复杂度分析

上述两节之后我们已经初步掌握了时间复杂度的分析方法,本节介绍均摊时间复杂度,均摊时间复杂度对应于算法中的摊还分析(或者叫平摊分析)。相比最好、最差、平均时间复杂度,均摊时间复杂度的使用场景更加特殊、更加有限。

 // array 表示一个长度为 n 的数组
 // 代码中的 array.length 就等于 n
 int[] array = new int[n];
 int count = 0;

 void insert(int val) {
    if (count == array.length) {
       int sum = 0;
       for (int i = 0; i < array.length; ++i) {
          sum = sum + array[i];
       }
       array[0] = sum;
       count = 1;
    }

    array[count] = val;
    ++count;
 }

这段代码实现了往数组中插入数据的功能。当数组满了之后,也就是代码中 count==array.length时,通过for循环遍历数组求和,并清空数组,将求和之后的sum值放到数组的第一个位置,然后再将心得数据插入。当数组一开始有空闲位置时,则直接将数据插入数组。

最好情况下时间复杂度:O(1),此时数组未满,并且由于count会自动执行加1操作,因此不用遍历找寻空位。

最坏情况下时间复杂度:O(n),此时数组装满,首先需要遍历数组的全部元素执行累加操作,接着将累加后的和放入到数组的0位置上,然后count执行加1操作指向下一个位置,后续操作与最好情况下时间复杂度吻戏类似。

平均时间复杂度:假设数组的长度为n,根据插入的位置不同,可以将其分为n中情况,每种情况的时间复杂度都为O(1),除此之外,还有一种当数组没有空闲位置时的情况,此时的时间复杂度为O(n),而且这n+1中情况发生的概率一样,都是$1/(n+1)$,所以根据加权平均的计算方法,平均时间复杂度为:

$1 * 1/(n+1) + 1 * 1/(n+1) ... + n * 1/(n+1) = O(1)$

到目前位置,最好情况下时间复杂度、最坏情况下时间复杂度、平均情况下时间复杂度的计算,理解起来都没有任何问题。但是这个例子的平均复杂度分析其实并不需要上述那样复杂,不需要引入概率论的知识。这是为什么呢?其实将本例的insert()和前面的find()进行对比,可以知道,find()函数在极端情况下复杂度才为O(1),但是insert在大部分情况下,时间复杂度都为O(1),只有当数组没有空闲位置时,采薇O(n)。其次对于insert(),O(1)时间复杂度的插入和O(n)时间复杂度的插入,出现的频率是非常有规律的,而且有一定的前后时序关系,一般都是一个O(n)插入只有,紧跟着$n-1$个O(1)的插入操作,循环往复。所以针对这种特殊的场景,我们引入了一种更加简单的分析方法:摊还分析法,通过摊还分析得到的时间复杂度,本文给其命名为均摊时间复杂度。那究竟如何使用摊还分析法来分析算法的均摊时间复杂度呢?

我们还是继续看在数组中插入数据的例子。每一次O(n)的插入操作,都会跟着n-1次O(1)的插入操作,所以把时间耗时多的那次操作均摊到接下来的n-1次耗时少的操作上,均摊下来,这一组连续的操作的均摊时间复杂度就是O(1),这就是均摊分析的大致思路。均摊时间复杂度和弹摊还分析的应用场景比较复杂,所以我们并不会经常用到。为了方便理解和记忆,本文总结了一下它们的应用场景。如果你以后遇到了,知道是怎么回事就行了。

对一个数据结构进行的操作中,大部分情况下时间复杂度都很低,只有个别情况下时间复杂度比较高,而且这些操作之间存在前后连贯的时序关系,这个时候,我们就可以将这一组操作放在一块儿分析,看是否能够将较高时间复杂度的那次操作的耗时平摊到其它时间复杂度较低的操作上。而且,在能够应用平摊时间复杂度的分析场景中,一般均摊时间复杂度就等于最好情况下的时间复杂度。

尽管许多数据结构和算法书籍都花了很大的力气来区分平均时间复杂度和均摊时间复杂度,但是其实我认为,均摊时间复杂度就是一种特殊的平均时间复杂度,我们没必要花太多的精力去区分它们。我们应该花时间去掌握它的分析方法,摊还分析法。至于分析出来的结果叫平均还是均摊,并不重要。

4.4 总结

之所以引入最好时间复杂度、最坏时间复杂度、平均时间复杂度、均摊时间复杂度这些概念,是因为很多算法,在不同的输入情况下,算法的时间复杂度不一样。在引入这些概念以后,我们能够更加全面的表示算法的时间复杂度。

// 全局变量,大小为 10 的数组 array,长度 len,下标 i。
int array[] = new int[10];
int len = 10;
int i = 0;

// 往数组中添加一个元素
void add(int element) {
   if (i >= len) { // 数组空间不够了
     // 重新申请一个 2 倍大小的数组空间
     int new_array[] = new int[len*2];
     // 把原来 array 数组中的数据依次 copy 到 new_array
     for (int j = 0; j < len; ++j) {
       new_array[j] = array[j];
     }
     // new_array 复制给 array,array 现在大小就是 2 倍 len 了
     array = new_array;
     len = 2 * len;
   }
   // 将 element 放到下标为 i 的位置,下标 i 加一
   array[i] = element;
   ++i;
}
/*答案:
最好时间复杂度O(1),最坏时间复杂度O(n),平均时间复杂度O(1),均摊时间复杂度为O(1)
假设数组的长度为n,当数组未满时,每次往数组中添加元素的时间复杂度都为O(1),当数组满时,需要O(n)的操作进行复制,并且这两个操作具有严格的时序关系,因此可以将复制的操作摊还给前面n-1次操作中,最终得到的时间复杂度仍然为O(1)
平均时间复杂度计算:
1 * 1/(n+1) + 1 * 1/(n+1)  ... + n * 1/(n+1)  = O(1)
*/

参考文献

协议

更多信息参见协议文件

署名-非商业性使用-禁止演绎

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].