初始数据结构--先导篇

作为一个文科生转行过来的程序媛,数据结构和算法的概念对我来说都是很难。虽然平时工作几乎很少用到算法,但是我总觉得如果不懂数据结构,在工作里面,我几乎不会去考虑业务之外的东西,比如性能,比如操作数组的时候,什么方法是最优的,这些都是隐藏需求。是我需要去突破的地方。

所以我决定硬着头皮啃一下试试。(主要还是跟着老师学,能不能学懂我没有太多信心,但是我希望我可以)
那从今天就进入数据结构和算法的美妙世界吧!

目的

学习数据结构和算法本身需要解决什么问题?
“快” 和“省”! 让代码运行更快,让我的代码更优雅,更节省存储空间。

鸡血😄

我们学习数据结构和算法,并不是为了死记硬背几个知识点。我们的目的是建立时间复杂度、空间复杂度意识,写出高质量的代码,能够设计基础架构,提升编程技能,训练逻辑思维,积攒人生经验,以此获得工作回报,实现你的价值,完善你的人生。
我被开篇的鸡血给打醒了, 哈哈哈哈

第一课,我学到的知识

  • 学习复杂度分析的好处

老师讲了很多关于复杂度分析的好处,和事后统计法的区别。但是我个人粗浅的理解是:不用事后统计,在写代码的时候就考虑自己写的代码的时间,空间复杂度,就能有效粗略估计算法的执行效率,事先的预防成本肯定是低于代码写好以后再来优化的成本的。

  • 大O 复杂度表示法

从CPU 的角度来看,代码的执行都是重复着:读数据-运算-写数据 的步骤。当我们写出来的每一段代码,如何“肉眼”估算他的计算时间呢?


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

上面这个例子。for 循环之外的代码都是运行一次,for 循环里面的代码运行n 次。所以复杂度就是T(n)


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

这次的代码里面有两个for 循环,还是嵌套的for 循环,那么第一个for 循环的运行次数是n ,第二个是n²

重要点:
所有的代码执行时间T(n) 和每行代码的执行次数n 成正比 总结成公式就是

T(n) = o(f(n))

这就是大 O 时间复杂度表示法。大 O 时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度(asymptotic time complexity),简称时间复杂度。

时间复杂度分析

  • 只关注代码里面循环次数最多的一段代码,并且排除掉常量,低阶, 系数。
    这个道理还是很好理解的吧,因为影响代码运行的最长时间,就是最复杂的那个。那些常量不管是多大,他都只会执行一次而已,无法对渐进时间复杂度产生影响,
  • 加法法则
  • 乘法法则: 嵌套代码的复杂度等于嵌套内外复杂度的成绩
    这个需要说明一下

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

这样的嵌套循环里,整个 cal() 函数的时间复杂度就是,T(n) = T1(n) * T2(n) = O(n*n) = O(n2)。

贴一个老师总结的复杂度量级


3723793cc5c810e9d5b06bc95325bf0a.jpg

对于以上的几种复杂度,我来谈一下我自己的理解

  • O(1)
    代码只会执行一次,是复杂度最低的,一般来说,只要代码里不存在循环语句,递归语句,正常的代码执行,不管多少行,他的复杂度都是O(1)

  • O(logn)、O(nlogn)

一般的循环,都可以归为这种的复杂度里面, 这里再次套用一下老师的一个例子


 i=1;
 while (i <= n)  {
   i = i * 2;
 }

这个例子里面,变量i 从1开始,每循环一次就乘以2,大于n 的时候才结束。
老师说这里是高中数学里面的等比数列。我就恍然大悟,然后再去复习了一下等比数列和对数。
这里代码的复杂度是 x=log2n 实际上,不管是以 2 为底、以 3 为底,还是以 10 为底,我们可以把所有对数阶的时间复杂度都记为 O(logn)。

对数之间是可以互相转换的,log3n 就等于 log32 * log2n,所以 O(log3n) = O(C * log2n),其中 C=log32 是一个常量。基于我们前面的一个理论:在采用大 O 标记复杂度的时候,可以忽略系数,即 O(Cf(n)) = O(f(n))。所以,O(log2n) 就等于 O(log3n)。因此,在对数阶时间复杂度的表示方法里,我们忽略对数的“底”,统一表示为 O(logn)。

  • O(m+n)、O(m*n)
    这个代码的复杂度是由两个数据的规模来决定的。
int cal(int m, int n) {
  int sum_1 = 0;
  int i = 1;
  for (; i < m; ++i) {
    sum_1 = sum_1 + i;
  }

  int sum_2 = 0;
  int j = 1;
  for (; j < n; ++j) {
    sum_2 = sum_2 + j;
  }

  return sum_1 + sum_2;
}

上面这个例子, m 和 n 是表示两个数据规模,我们不知道两个谁的量级更大,所以就是 :T1(m)*T2(n) = O(f(m) * f(n))。
上面的例子是这里其实我没太理解,不过我感觉我应该用不到这么复杂的,就先不追究了

空间复杂度分析

其实空间复杂度分析和时间复杂度分析很类似。看下面的例子


void print(int n) {
  int i = 0;
  int[] a = new int[n];
  for (i; i <n; ++i) {
    a[i] = i * i;
  }

  for (i = n-1; i >= 0; --i) {
    print out a[i]
  }
}

在这个例子里面,首先我们申请了一个 i 的空间变量, 他是常量阶的,和数据规模n 没有关系,在for 里面,申请了一个n 长度的数组。所以整个代码的空间复杂度是O(n)
我们常见的空间复杂度就是 O(1)、O(n)、O(n2 ),像 O(logn)、O(nlogn) 这样的对数阶复杂度平时都用不到。
所以我暂时按照时间复杂度分析 的规律来理解空间复杂度,应该没有什么问题吧。

课后思考

有人说,我们项目之前都会进行性能测试,再做代码的时间复杂度、空间复杂度分析,是不是多此一举呢?而且,每段代码都分析一下时间复杂度、空间复杂度,是不是很浪费时间呢?你怎么看待这个问题呢?

针对这个问题,其实从我个人而言,我粗浅的理解为: 对代码进行分析,就会和host 没有关系,对代码进行性能测试的话,可能受浏览器的内核,版本等等之类的影响。还有一个先后顺序的问题,但是实际上在工作中,普通的项目,做了其一应该就ok 了吧。

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