数据结构与算法总结

概念

1,算法:解决问题的思路与方法。
2,数据结构:为了算法更好的处理问题而总结定义的一组数据规则。

  • 物理结构:数据在磁盘上的存储结构,分为连续存储与非连续存储。对应的逻辑结构:数组与链表。
  • 逻辑结构:针对常见问题归纳定义的一套数据规则。常见的:数组,链表,栈,队列,散列表,跳表,二叉树,图。最终对应到磁盘或内存中只有连续与非连续存储。

3,算法设计的标准:在最短的时间内使用最少的资源获取一个准确的结果

  • 有穷性,确定性,可行性。比如:循环必须有结束条件,每一步不能出现歧义。最终结果保证准确。
  • 算法尽量保证可读性,便于阅读与交流。
  • 代码健壮,需要考虑边界条件与特殊情况,每一种场景都需要闭环处理。
  • 高效率:对应算法的执行速度快,可以参考时间复杂度进行定量的判断。
  • 低内存:执行算法运行需要的内存尽量少,可以参考空间复杂度度进行判断。

算法复杂度分析

1,在设计算法时必须考虑准确性 ,而效率与空间有时需要根据数据规模,设备性能等综合考虑,最优解可能不是效率最高,内存最小的。其中需要考虑空间换时间或时间换空间的策略。此时需要通过对算法的复杂度进行分析获取最优解。
2,算法的复杂度只能初步估算算法的执行效率,而不能代码算法的真实执行效率。一般数据量越大,越接近分析的趋势。表示方式:大O复杂度表示法。

时间复杂度

用于判断算法的执行效率,表示代码执行的时间随数据规模增长的变化趋势。针对单一设置场景可以通过模拟打印执行时间进行统计比较。

分析方法:

1,统计代码执行的次数时,默认不同的操作执行时间相同(比如:a+b 与 ab 默认都是统计一次,实际加法的执行效率更高)。
2,多段代码执行时只关心循环次数最多代码的复杂度。即总复杂度等于量级最大代码段的复杂度,遵循加法原则。
3,复杂度分析时忽略常量的影响,前提条件是数据规模n相对很大。比如f(n) = 20
n^2 +1000,当n非常大时,复杂度表示为:O(n) = n^2。而当n较小时,比如n=5,此时常量不能省略,需要参与多种算法性能的比较。
4,嵌套代码的复杂度 = 多层代码复杂度的乘积,遵循乘法原则。

常见的复杂度

1,常量级别:O(1):代表算法执行的次数固定,不随数据规模增长。

//获取平方和代码执行的次数为3,但时间复杂度表示O(1)而不是O(3)
public int square(int a, int b) {
   a *= a;
  b *= b;
  return a + b;
}

2,对数级别:O(logn),O(nlogn):常见的场景:二分查找的时间复杂度logn。归并排序的时间复杂度nlongn

//二分查找的前提时:数组datas有序。此时最多执行次数logn,以2为底数。根据乘法原则,外层加个循环调用,时间复杂度为O(nlogn)。
public int find(int[] datas, int num) {
        int index = -1;
        int start = 0;
        int end = datas.length - 1;
        if (datas[start] > num || datas[end] < num) {
            return index;
        }
        while (start <= end) {
            int middle = ((end - start) >> 1) + start;
            if (datas[middle] == num) {
                return middle;
            } else if (datas[middle] < num) {
                start = middle + 1;
            } else {
                end = middle - 1;
            }
        }
        return index;
    }

3,多次级别:O(n2),O(n3)等。一般场景为多个循环嵌套,遵循乘法原则。常见的有冒泡排序

//双层for循环,执行次数为n^2。时间复杂度O(n^2)
public void sort(int[] datas) {
  int n = datas.length;
  if (n < 2) {
    return;
  }
  for (int i = 0; i < n - 1; i++) {
    for (int j = i + 1; j < n; j++) {
      if (datas[i] > datas[j]) {
        int tem = datas[i];
        datas[i] = datas[j];
      }
    }
  }
}

4,NP级别(时间复杂度为非多项式量级的算法问题叫做NP问题):O(n!),O(2^n)。特点是随着n的增大执行时间会急剧增加。一般使用暴力枚举产生的,可以考虑使用动态规划,贪心等进行优化。常见的:n个字符串找最长相同的字符串,n个物品选中与不选。

//执行次数:(n-1)*(n-2)*(n-3)*...*(2)*。字符串比较不考虑长度,默认当做一次。此时时间复杂度为O(n!)
public String findSame(String[] datas) {
  int n = datas.length;
  String result = "";
  for (int i = 0; i < n - 1; i++) {
    String tem = datas[i];
    if (find(tem, i + 1, datas)) {
      if (result.length() < tem.length()) {
        result = tem;
      }  
    }
  }
  return result;
}

private boolean find(String str, int start, String[] datas) {
  int n = datas.length;
  for (int i = start; i < n; i++) {
    if (str.equals(datas[i])) {
      return true;
    }
  }
  return false;
}

5,通常时间复杂度排序:O(1)常数阶 < O(log n)对数阶 < O(n)线性阶 < O(n^2)平方阶 < O(n^3)立方阶 < O(2^n) 指数阶。在leetcode中根据算法的复杂度和数据规模,一般执行次数超过10^7会出现算法超时,此时应该优化算法使时间复杂度的级别更小。

不同规模复杂度的趋势.png
复杂度分类:

1,最好情况时间复杂度:在理想情况下,执行代码的时间复杂度。比如使用break,return等打断循环时,如果执行结果在index=0的位置时,此时时间复杂度为:O(1)
2,最坏情况时间复杂度:在最坏的情况下,执行代码的时间复杂度。
3,平均情况时间复杂度:综合考虑最好,最坏情况以及出现的概率,计算时间复杂度的平均值。
4,均摊时间复杂度:通过对最坏情况时间复杂度进行分摊的方式,快速分析平均时间复杂度的方法。

//无序数组中查找元素。最好时间复杂度:O(1),最坏时间复杂度:O(n),平均时间复杂度:O(n)
//平均次数:((1+2+3+....n-1) + n*(n-1))/n
public int find(int[] datas, int num) {
  int n = datas.length;
  for (int i = 0; i < n; i++) {
    if (datas[i] == num) {
      return i;
    }
  }
  return -1;
}

//数组赋值时,大部分时间复杂度为:O(1),遇到扩容时复杂度为:O(n)。根据出现的频率,将扩容均摊到每次的赋值中,时间复杂度为:O(1)
private int[] datas = new int[16];
private int size = 16;
private int count = 0;
    
public void add(int num) {
  if (count < size) {
    datas[count] = num;
  } else {
    //数组扩容
    size <<= 1;
    int[] tem = Arrays.copyOf(datas, size);
    datas = tem;
    datas[count] = num;
  }
  count++;
}

空间复杂度

用于估算算法执行过程中占用的空间。与时间复杂度分析方式相同。常见的复杂度:O(1),O(n),O(n^2),O(logn),O(nlogn)。

  • 存储二进制数时,输入的空间复杂度为O(logn)bit。比如:输入8使用二进制表示3个bit,对应输入n使用logn个bit。
对于时间复杂度与空间复杂度不需要追求单一最优解,有时需要增加空间复杂度换区时间复杂度的减小。比如:背包问题使用暴力枚举的方式:空间复杂度:O(1),时间复杂度为:O(2^n)。使用动态规划进行优化后:空间复杂度:O(n),时间复杂度为:O(nV)。有时需要增加时间复杂度来减少空间复杂度。比如:图的存储和查找。

常见的数据结构(逻辑结构)

线性结构

1,数组
2,链表
3,栈
4,队列
5,散列表

1,二叉树
2,多路查找树
3,堆

1,图的存储
2,图的搜索
3,图的排序

常见的算法

常见的排序

1,冒泡排序
2,插入排序
3,选择排序
4,快速排序
5,归并排序
6,堆排序
7,基数排序
8,桶排序

搜索

1,广度优先搜索bfs
2,深度优先搜索dfs
3,A*启发式搜索

查找

1,线性二分查找

字符串匹配

动态规划

贪心算法

分治算法

回溯算法

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容

  • 什么是数据结构?什么是算法? 广义来讲,数据结构是相互之间存在一种或多种特定关系的数据元素的集合,它不仅存储数据,...
    Edwin_天寻阅读 450评论 0 1
  • 1. 链表 链表是最基本的数据结构,面试官也常常用链表来考察面试者的基本能力,而且链表相关的操作相对而言比较简单,...
    Mr希灵阅读 1,439评论 0 20
  • 1.语言:C/OC2.环境:Leetcode/Xcode#1.数组1.连续存储空间,对内存友好;2.随机访问第K个...
    mengjz阅读 188评论 0 1
  • 数据结构和算法总结 一、排序算法 1.1、排序分类 1.内部排序 指将需要处理的所有数据都加载到内部存储器(内存)...
    Anthons阅读 214评论 0 0
  • 为什么学习数据结构与算法? 关于数据结构和算法,以前只是看过一些零散的文章或者介绍,从来都没有系统的去学习过。随着...
    李大酱的大脖子阅读 927评论 0 0