美文网首页iOS 设计模式 && 算法@IT·互联网程序员
老夫反手就是一张过去的CD,听听那是算法时间复杂度和大O表示法

老夫反手就是一张过去的CD,听听那是算法时间复杂度和大O表示法

作者: 香脆的大鸡排 | 来源:发表于2017-05-29 01:07 被阅读880次

现在是伟大美好的端午佳节时间,你是在回家的路上吗?祝各位简友们生日快乐!!!啪啪啪! 又调皮,明明是中秋节快乐好咩~。

今日有酒尽早醉,明日无酒老夫我开盖再来一瓶。 咱今天扒一下软件编程中的算法时间复杂度。

“玛德,智 ........勇双全。一说算法之类的东西晚生我就想打哈欠,犯困。(o-ωq)).oO ”

“是不是感觉老有知识咳不出来,又咽不下去?老夫反手就是一张过去的CD,听听那是我们的XX”

“巴拉拉能量,麻辣割鸡小魔仙全身变。kuang!别担心,大鸡排今天讲的足够简单、 粗暴不戴X,易理解。” 快坐上来吧,搞起。搞起。


目录

  • 前言
  • 概念
  • 例子
  • 题外话

前言

到今天为止,可能我们的确不会自己再去经常编写一个高效的算法。因为在各大框架或语言原生的API里,它们已经帮业务开发的程序员将最优的算法都实现了。所以我们很少用到在实际场景中,特别是作为大前端开发人员更加很少接触到。但是无论从计算机编程基础、以及编写更优秀的性能代码,这块的知识是任然是非常重要的。

基础与流行

人的一生是有限的,个人认为在编程技术栈中的学习即是一种投资行为。做我们这行的行业积累是会过期的。所以我将技术知识粗略的划分为两块。
即:基础编程知识流、流行编程知识流。
基础知识是牢固而不容易过期的,而流行编程知识往往是偏向前沿技术而活泼不稳定的,把时间轴拉长来看,新技术是不断的被迭代的。

也就是说如果我们把 sql、算法、编程思想 ...归结为基础编程知识来看。java语言、kotlin语言、android、React ...这种知识是当前流行编程知识流。

那么流行知识是一个反复学习新技术,不断的扔掉成旧知识的一个过程。而恰恰相反,基础知识是不会和新技术产生冲突交集的。所以如果你是一个刚刚入行不久的攻城狮,那么从投资的角度来看,我建议对基础编程知识的前期投资是越丰厚越好,而且是稳赚不陪的卖买。
正式开发环境中很多时候是飞机大炮造到一半,发现零件的质量不够好。框架子搞了一堆再牛逼,却写不出好东西或则说无法发挥最大的性能。

用优质的代码解决硬件成本

简单来说,就是如果你代码的执行算法太慢,将导致需要用硬件来撑起运行速度。这就是在过多的消耗硬件成本。而作为行业内人员或者boss,你是愿意将刀刃(钱)用在优秀的工程师上,还是高昂价格的机器上。相信这个问题,我只需要提出,你就已经有了结论。我不作过多的阐述。


概念

我们今天只弄明白两点,到底什么是算法时间复杂度?什么是大O表示法?

算法时间复杂度

好,怎么理解?一句话来说就是
你用代码做某一件事件,所消耗的总体时间长度,就是该事件(算法)的时间复杂度。
这里暂且不说平均复杂度和实际复杂度。我们后面再讲这些。

大O表示法

大O表示法呢?
一个用来表示算法时间复杂度的公式名称,用于指出该算法的效率有多快。在计算机领域我们用函数来表示
当我第一次接触到大O表示法时,我还在纠结,那小o表示法又是什么。其实根本没有这种东西。大O表示法仅仅是一个名称。

//表达式其中n表示要执行的次数。
 O(n)

例子

  • O(n) 傻找算法(线性时间)
  • O(log n) 二分查找

黑魔法大鸡排把你的老婆抓起来藏在召唤师峡谷的地窖中。依照你过人的聪明智慧,你用敏锐的嗅觉一路上根据老婆的味道,靠鼻子闻到了地窖。打开一看。里面有1000个和你老婆一模一样的蜡像,但其中有一个是真正的老婆。放眼望去,你并不知道哪个是你的老婆,因为他们实在太像了。由于被大鸡排下了诅咒,真正的老婆被封印了起来,只有通过真爱么么哒才能唤醒 (づ ̄3 ̄)づ╭❤~。

O(n) 傻找算法(线性时间)

此刻你急中生智,骂道:“什么烂剧情例子,用鼻子闻到老婆的味道跟我聪明的智慧有个毛关系啊?,还tm要一个么么哒”,你只好决定一个一个亲下去。从第一个亲到最后一个
我们用代码来表示这个过程就是:

//999个假老婆+一个真的
List<Wife> Wifes= {蜡像,蜡像,蜡像...真老婆,蜡像};
// 我自己
 Lead myself =new Lead();

for(i=0; i<=Wifes.length; ++i){
  boolean  resurrection =kiss(Wifes.get(i)); //么么哒唤醒
  if(resurrection ){
     Log.i(“已找到老婆他在”+i+“个,赶紧抬回家,远离召唤师峡谷”);
     return ;
  }
}

 boolean  kiss(Wife mWife){
  //调用自己的么么哒方法 返回真假
 return myself.kiss(mWife);
}

这个过程是我们有一个Wifes容器装下了999个蜡像和一个真正的老婆。然后myself 是自己,拥有一个kiss方法用来唤醒老婆并返回真假。这里模拟从第一个开始kiss到最后一个。当我们找到了老婆就停止一切行为。

那么我们的时间复杂度是:最多尝试1000次,即** O(n)来表示,其中n**表示次数。是不是很简单。

这是最糟糕的结果,大鸡排将你的wife放在最后一个位置,你从第一个开始亲,亲到最后一个。你需要尝试1000次。但绝不会超过这个范围。当然实际情况也可能是O(1),第一次成功了。

我们通过这个算法得到了时间复杂度公式: O(n)

O(log n) 二分查找

接着上面的列子。还记得召唤师峡谷里有个商店老爷爷吗?他说能为你打开此次寻找的天机。将所有蜡像的序号都展示出来,并且他每次都能告诉你整个区间内是否存在真正的老婆。你想了想那么我可以从中间对折拆分找呀,这样可以每次直接排除掉一半。这个过程就像:

第一次询问:** 500~1000** 他说不存在, 1~499那么一定存在。
第二次询问:** 250~499** 他说不存在, 1~249那么一定存在。
第三次询问:** 125~249** 他说不存在, 1~124那么一定存在。
第四次询问:** 63~124** 他说不存在, 1~62那么一定存在。
第五次询问:** 31~62** 他说不存在, 1~30那么一定存在。
第六次询问:** 15~30** 他说不存在, 1~15那么一定存在。
第七次询问:** 7~14** 他说不存在, 1~6那么一定存在。
第八次询问:** 3~6** 他说不存在, 1~2那么一定存在。
第九次询问:** 2** 他说不对,那么结果只剩下1了。

好,我们捋一捋。实际每次询问我们都可以排除一半绝对不可能存在的。也就是说最多我们需要经过9步即可完成从1000个老婆中出真正的老婆。
如果我们把它写成代码就会是这个样子:

//999个假老婆+一个真的
List<Wife> Wifes= {蜡像,蜡像,蜡像...真老婆,蜡像};
// 我自己
 Lead myself =new Lead();

int low=0; //最低位
int high = Wifes.length-1; //最高位
int mid; //折中猜想数

  while( low<=high){
       mid=(low+higt)/2
      likeWife=Wifes.get(mid);
      if( kiss(likeWife)){
          Log.i(“已找到老婆他在”+mid+“个,赶紧抬回家,远离召唤师峡谷”);
          return ;
      }
    boolean  deviation=  elderlyHelp(likeWife);
      if(deviation){ //往左偏移 表示大了
      high=mid-1;
      }esle{  //往右偏移 表示小了
      low=mid+1;
    }
  }

}

//老爷爷的帮助 返回区间内是否包含
boolean   elderlyHelp(){
  ····
}  

 boolean  kiss(Wife mWife){
  //调用自己的么么哒方法 返回真假
 return myself.kiss(mWife);
}

这样我们就推倒出二分法查找实际是是对数函数的反向幂运算。所以推倒出公式为:O(log n)

稍微说一下log对数运算,也许你学过又忘了。log以10为底数多少次幂结果等于100,其实就是指多少个10相乘的结果为100。答案是两个:10 × 10 = 100。所以log以10为底数的 2次幂等于100。

O(n)对比 O(log n)

假定我们每一次myself.kiss用于激活的方法需要1秒钟执行。当采用第一种算法时,时间复杂度为O(n) ,那么需要1000秒才能找出老婆。但如果采用了二分查找,时间复杂度为 O(log n) ,那么仅需要9秒即可完成操作。其中n表示次数。那么由此可见O(log n) 比O(n)要快。当元素越多的时候,执行的效率就尤其具有可比性。


题外话

好,那么到这里就讲完了今天的内容啦。如果你感兴趣的话可以再去了解O(n!) n阶乘的时间复杂度。当n阶越高,消耗的时间越长。这是计算机领域非常经典的旅行商问题。 感兴趣戳这里过去继续深入阅读。

旅行推销员问题(英语:Travelling salesman problem, TSP)是这样一个问题:给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。它是组合优化中的一个NP困难问题,在运筹学理论计算机科学中非常重要。

看完本篇并不能让你成一个优秀的工程狮,这是入门级别的基础知识。但如果因为是你看完这篇文章后产生了这种想法,我的目的就达到了,至少已经在通往优秀工程狮的路上了。那么更多的知识还需要长久的打磨和学习。共勉 加油!


如何下次找到我?

相关文章

  • 老夫反手就是一张过去的CD,听听那是算法时间复杂度和大O表示法

    现在是伟大美好的端午佳节时间,你是在回家的路上吗?祝各位简友们生日快乐!!!啪啪啪! 又调皮,明明是中秋节快乐好咩...

  • 简单的时间复杂度计算法则

    简单算法时间复杂度计算 大O表示法 像前面用O( )来体现算法时间复杂度的记法,我们称之为大O表示法。 算法复杂度...

  • 复杂度分析

    1. 大 O 复杂度表示法 时间复杂度就是算法的执行效率,也就是算法代码执行的时间; 大 O 时间复杂度实际上并不...

  • 【python】二分法和选择排序法的实现

    一、大O表示法 学算法就绕不开大O表示法,大O法可以告诉我们算法的时间和空间复杂度。 我们先聊点简单的,请你从1数...

  • 排序算法

    复杂度 常用大O表示法展示算法的时间复杂度和空间复杂度。大O时间复杂度表示代码执行时间随数据规模变化的趋势。下面是...

  • 算法复杂度

    一、大O表示法 算法的时间复杂度通常用大O符号表述 大O表示法 : ,n为算法所需要执行的操作数 该表示法的操作数...

  • 时间复杂度了解一下

    大O表示法是用来表示算法的性能和复杂度的,也表示算法占用cpu的情况。 通常有以下几种表示: 1、O(1)复杂度 ...

  • 时间复杂度 BigO

    时间复杂度 BigO [大O表示法] 算法的渐进时间复杂度 T(n) = O(f(n)) T(n) -- 时间的渐...

  • 大O表示法

    讨论算法必提到O(),不太懂,尝试理解一下。 大O表示法 描述算法的性能和复杂度。常用O表示。一般考虑为cpu时间...

  • 数据结构与算法--时间空间复杂度(基础篇)

    时间复杂度分析 大O复杂度表示法 大O时间复杂度实际上并不具体表示代码真正的执行时间,而是表示算法的执行时间随数据...

网友评论

  • 庞哈哈哈12138:厉害的小哥哥
  • 小苗晓雪:我就喜欢听段子!
  • 每天都有新的太阳:鸡排兄,给力,望持续码出经典软文
    香脆的大鸡排:@每天都有新的太阳 :heart: 好的 老铁
  • smallstrong:文章前戏做的很赞~:smile:
    香脆的大鸡排:@smallstrong :grin: 谢谢
  • 58f0c74fbe82:你写的文章看起来一点都不枯燥,我想问一下现在自学android还有希望吗?
    香脆的大鸡排:@随缘销旧业 你之前做什么行业的?
    58f0c74fbe82: @香脆的大鸡排 我对android挺感兴趣的,可是我已经挣扎了快2年了,我还没有学会,我花在学习上的时间太少了,因为我潜意识中总是一直在逃避这些东西,总觉的太难了,可是我已经没有退路了,我不想再逃避了,因为两年前我就裸辞了,我只想早点进入软件开发这行,请前辈指条明路!
    香脆的大鸡排:@随缘销旧业 看你为什么学习了,如果单纯混口饭吃,还是不要学安卓了,后端更稳定。越偏用户体验的科目更新越快,目前初中级市场一直处于饱和状态。如果是为了兴趣,我想没有什么可以成为你学习的绊脚石。并且安卓的可玩性,和学习性还是很高的。

本文标题:老夫反手就是一张过去的CD,听听那是算法时间复杂度和大O表示法

本文链接:https://www.haomeiwen.com/subject/lhphfxtx.html