算法复杂度的表示法_用简单的英语算法:时间复杂度和Big-O表示法

算法复杂度的表示法

by Michael Olorunnisola

通过Michael Olorunnisola

用简单的英语算法:时间复杂度和Big-O表示法 (Algorithms in plain English: time complexity and Big-O notation)

Every good developer has time on their mind. They want to give their users more of it, so they can do all those things they enjoy. They do this by minimizing time complexity.

每个优秀的开发人员都有自己的时间。 他们想给用户更多的东西,以便他们可以做自己喜欢的所有事情。 他们通过最小化时间复杂度来做到这一点。

Before you can understand time complexity in programming, you have to understand where it’s most commonly applied: in the design of algorithms.

在您了解编程中的时间复杂性之前,您必须了解它最常应用的地方:在算法设计中。

那么,什么是算法? (So what’s an algorithm, anyway?)

Simply put, an algorithm is a series of contained steps, which you follow in order to achieve some goal, or to produce some output. Let’s take for example your grandma’s recipe for baking a cake. Wait, does that count as an algorithm? Sure it does!

简而言之,算法是一系列包含的步骤,为了实现某些目标或产生某些输出,必须遵循这些步骤。 让我们以您奶奶的烤蛋糕食谱为例。 等等,算作算法吗? 当然可以!

function BakeCake(flavor, icing){
"1. Heat Oven to 350 F2. Mix flour, baking powder, salt3. Beat butter and sugar until fluffy4. Add eggs.5. Mix in flour, baking powder, salt6. Add milk and " + flavor + "7. Mix further8. Put in pan9. Bake for 30 minutes
10." + if(icing === true) return 'add icing' + "
10. Stuff your face
"
}BakeCake('vanilla', true) => deliciousness

Algorithms are useful in our examination of time complexity because they come in all shapes and sizes.

由于算法具有各种形状和大小,因此在我们检查时间复杂度方面很有用。

In the same way you can slice a pie a 100 different ways, you can solve a single problem with many different algorithms. Some solutions are just more efficient, taking less time and requiring less space than others.

以相同的方式,您可以用100种不同的方式对一个饼进行切片,可以使用许多种不同的算法来解决一个问题。 与其他解决方案相比,某些解决方案效率更高,所需时间更少,占用的空间更少。

So the main question is: how do we go about analyzing which solutions are most efficient?

因此,主要问题是:我们如何分析哪些解决方案最有效?

Math to the rescue! Time complexity analysis in programming is just an extremely simplified mathematical way of analyzing how long an algorithm with a given number of inputs (n) will take to complete it’s task. It’s usually defined using Big-O notation.

求救数学! 编程中的时间复杂度分析只是一种极其简化的数学方法,用于分析具有给定数量输入(n)的算法完成任务所需的时间。 通常使用Big-O表示法定义。

您问什么是大O符号? (What’s Big O notation, you ask?)

If you promise you won’t give up and stop reading, I will tell you.

如果您保证不会放弃并停止阅读,我会告诉您。

Big-O notation is a way of converting the overall steps of an algorithm into algebraic terms, then excluding lower order constants and coefficients that don’t have that big an impact on the overall complexity of the problem.

Big-O表示法是一种将算法的整体步骤转换为代数项,然后排除对问题的整体复杂性影响不大的低阶常量和系数的方法。

Mathematicians will probably cringe a bit at my “overall impact” assumption there, but for developers to save time, it’s easier to simplify things this way:

数学家可能会对我的“总体影响”假设有些畏缩,但是对于开发人员来说,为了节省时间,用这种方式简化事情会更容易:

Regular       Big-O2             O(1)   --> It's just a constant number2n + 10       O(n)   --> n has the largest effect5n^2          O(n^2) --> n^2 has the largest effect

In short, all this example is saying is: we only look at the factor in our expression that has the potential greatest impact on the value that our expression will return. (This changes as the constant gets extremely large and n gets small, but let’s not worry about that for now).

简而言之,此示例说明的是:我们仅查看表达式中对表达式返回的值具有最大潜在影响的因素。 (随着常数变得非常大而n变得很小,这种情况会发生变化,但是现在我们不必担心这一点)。

Below are some common time complexities with simple definitions. Feel free to check out Wikipedia, though, for more in-depth definitions.

以下是一些具有简单定义的常见时间复杂性。 请随意查看Wikipedia ,以获得更深入的定义。

  • O(1) — Constant Time: Given an input of size n, it only takes a single step for the algorithm to accomplish the task.

    O(1)-恒定时间:给定大小为n的输入,算法只需一步即可完成任务。
  • O(log n) — Logarithmic time: given an input of size n, the number of steps it takes to accomplish the task are decreased by some factor with each step.

    O(log n)-对数时间:给定大小为n的输入,完成任务所需的步骤数会因每个步骤而减少一些。
  • O(n) — Linear Time: Given an input of size n, the number of of steps required is directly related (1 to 1)

    O(n)—线性时间:给定大小为n的输入,所需的步数直接相关(1到1)
  • O(n²) — Quadratic Time: Given an input of size n, the number of steps it takes to accomplish a task is square of n.

    O(n²)—二次时间:给定大小为n的输入,完成一项任务所需的步骤数为n的平方。
  • O(C^n) — Exponential Time: Given an input of size n, the number of steps it takes to accomplish a task is a constant to the n power (pretty large number).

    O(C ^ n)—指数时间:在输入大小为n的情况下,完成一项任务所需的步骤数是n次幂的常数(相当大的数字)。

With this knowledge in hand, lets see the number of steps that each of these time complexities entails:

掌握了这些知识之后,让我们看一下这些时间复杂度所需要的步骤数:

let n = 16;O (1) = 1 step "(awesome!)"O (log n) = 4 steps  "(awesome!)" -- assumed base 2O (n) = 16 steps "(pretty good!)"O(n^2) = 256 steps "(uhh..we can work with this?)"O(2^n) = 65,536 steps "(...)"

As you can see, things can easily become orders of magnitude more complex depending on the complexity of your algorithm. Luckily, computers are powerful enough to still handle really large complexities relatively quickly.

如您所见,根据算法的复杂性,事情很容易变得复杂几个数量级。 幸运的是,计算机功能强大,仍然可以相对快速地处理非常大的复杂性。

So how do we go about analyzing our code with Big-O notation?

那么,我们如何使用Big-O表示法分析代码?

Well here are some quick and simple examples of how you can apply this knowledge to algorithms you might encounter in the wild or code up yourself.

好了,这里有一些快速简单的示例,说明如何将这些知识应用于野外可能遇到的算法或自己编写代码。

We’ll use the data structures below for our examples:

我们将使用以下数据结构作为示例:

var friends = {'Mark' : true,'Amy' : true,'Carl' : false,'Ray' :  true,
'Laura' : false,
}
var sortedAges = [22, 24, 27, 29, 31]

O(1)-恒定时间 (O(1) — Constant Time)

Value look ups when you know the key (objects) or the index (arrays) always take one step, and are thus constant time.

当您知道键(对象)或索引(数组)总是迈出一步,并且时间恒定时,就会进行值查找。

//If I know the persons name, I only have to take one step to check:function isFriend(name){ //similar to knowing the index in an Array return friends[name]; 
};isFriend('Mark') // returns True and only took one stepfunction add(num1,num2){ // I have two numbers, takes one step to return the valuereturn num1 + num2
}

O(log n)-对数时间 (O(log n) — Logarithmic Time)

If you know which side of the array to look on for an item, you save time by cutting out the other half.

如果您知道要在阵列的哪一侧查找某项,则可以省去另一半来节省时间。

//You decrease the amount of work you have to do with each stepfunction thisOld(num, array){var midPoint = Math.floor( array.length /2 );if( array[midPoint] === num) return true;if( array[midPoint] < num ) --> only look at second half of the arrayif( array[midpoint] > num ) --> only look at first half of the array//recursively repeat until you arrive at your solution}thisOld(29, sortedAges) // returns true //Notes//There are a bunch of other checks that should go into this example for it to be truly functional, but not necessary for this explanation.//This solution works because our Array is sorted//Recursive solutions are often logarithmic//We'll get into recursion in another post!

O(n)—线性时间 (O(n) — Linear Time)

You have to look at every item in the array or list to accomplish the task. Single for loops are almost always linear time. Also array methods like indexOf are also linear time. You’re just abstracted away from the looping process.

您必须查看数组或列表中的每个项目才能完成任务。 单次for循环几乎总是线性时间。 像indexOf这样的数组方法也是线性时间。 您只是从循环过程中抽象出来。

//The number of steps you take is directly correlated to the your input sizefunction addAges(array){var sum = 0;for (let i=0 ; i < array.length; i++){  //has to go through each valuesum += array[i]}return sum;
}addAges(sortedAges) //133

O(n²)—二次时间 (O(n²) — Quadratic Time)

Nested for loops are quadratic time, because you’re running a linear operation within another linear operation (or n*n = n²).

嵌套的for循环是二次时间,因为您正在另一个线性运算(或n * n =n²)内运行线性运算。

//The number of steps you take is your input size squaredfunction addedAges(array){var addedAge = [];for (let i=0 ; i < array.length; i++){ //has to go through each valuefor(let j=i+1 ; j < array.length ; j++){ //and go through them againaddedAge.push(array[i] + array[j]);}}return addedAge;
}addedAges(sortedAges); //[ 46, 49, 51, 53, 51, 53, 55, 56, 58, 60 ]//Notes//Nested for loops. If one for loop is linear time (n)//Then two nested for loops are (n * n) or (n^2) Quadratic!

O(2 ^ n)—指数时间 (O(2^n) — Exponential Time)

Exponential time is usually for situations where you don’t know that much, and you have to try every possible combination or permutation.

指数时间通常用于您不太了解的情况,并且您必须尝试所有可能的组合或排列。

//The number of steps it takes to accomplish a task is a constant to the n power//Thought example//Trying to find every combination of letters for a password of length n

You should do time complexity analysis anytime you write code that has to run fast.

每当您编写必须快速运行的代码时,都应该进行时间复杂度分析。

When you have various routes to solve a problem, it is definitely wiser to create a solution that just works first. But in the long run, you’ll want a solution that runs as quickly and efficiently as possible.

当您有各种解决问题的途径时,明智的做法是首先创建一个解决方案。 但是从长远来看,您将需要一个尽可能快速高效地运行的解决方案。

To help you with the problem solving process, here are some simple questions to ask:

为了帮助您解决问题,以下是一些简单的问题:

1. Does this solve the problem? Yes =>

1.这样可以解决问题吗? =>

1. Does this solve the problem? Yes =>

1.这样可以解决问题吗? =>

2. Do you have time to work on this

2.您有时间从事此工作吗

2. Do you have time to work on this

2.您有时间从事此工作吗

2. Do you have time to work on thisYes => go to step 3

2.您是否有时间进行此工作, =>转到步骤3

2. Do you have time to work on thisYes => go to step 3

2.您是否有时间进行此工作, =>转到步骤3

2. Do you have time to work on thisYes => go to step 3No => Come back to it later and go to step 6 for now.

2.您是否有时间进行此工作 =>转到步骤3 =>稍后再回到步骤6,现在转到步骤6。

2. Do you have time to work on thisYes => go to step 3No => Come back to it later and go to step 6 for now.

2.您是否有时间进行此工作 =>转到步骤3 =>稍后再回到步骤6,现在转到步骤6。

3. Does it cover all edge cases? Yes =>

3.它涵盖所有边缘情况吗? =>

3. Does it cover all edge cases? Yes =>

3.它涵盖所有边缘情况吗? =>

4. Are my complexities as low as possible ?

4.我的复杂程度是否尽可能低?

4. Are my complexities as low as possible ?

4.我的复杂程度是否尽可能低?

4. Are my complexities as low as possible ?No => rewrite or modify into a new solution –>go back to step 1

4.我的复杂程度是否尽可能低? =>重写或修改为新解决方案–>返回步骤1

4. Are my complexities as low as possible ?No => rewrite or modify into a new solution –>go back to step 1

4.我的复杂程度是否尽可能低? =>重写或修改为新解决方案–>返回步骤1

4. Are my complexities as low as possible ?No => rewrite or modify into a new solution –>go back to step 1Yes => go to step 5

4.我的复杂程度是否尽可能低? =>重写或修改为新解决方案–>返回步骤1 =>转到步骤5

4. Are my complexities as low as possible ?No => rewrite or modify into a new solution –>go back to step 1Yes => go to step 5

4.我的复杂程度是否尽可能低? =>重写或修改为新解决方案–>返回步骤1 =>转到步骤5

5. Is my code D.R.Y ? Yes =>

5.我的代码是DRY吗? =>

5. Is my code D.R.Y ? Yes =>

5.我的代码是DRY吗? =>

6. Rejoice!

6.欢喜!

6. Rejoice!

6.欢喜!

6. Rejoice!No => Make it D.R.Y, then rejoice!

6.欢喜! =>使其干燥,然后高兴!

Analyze time complexity any and all times you are trying to solve a problem. It’ll make you a better developer in the log run. Your teammates and users will love you for it.

您尝试解决问题的所有时间都要分析时间复杂度。 它可以使您成为日志运行中更好的开发人员。 您的队友和用户将为此而爱您。

Again, most problems you will face as programmer — whether algorithmic or programmatic — will have tens if not hundreds of ways of solving it. They may vary in how they solve the problem, but they all still solve that problem.

同样,您将以编程人员的身份遇到的大多数问题,无论是算法上还是程序上的问题,都有数十种甚至数百种解决方法。 他们解决问题的方式可能有所不同,但是他们仍然都能解决问题。

You could be making decisions between whether to use sets or graphs to store data. You could be deciding whether or not to use Angular, React, or Backbone for a team project. All of these solutions solve the same problem in a different way.

您可能在决定使用集还是使用图来存储数据之间做出决定。 您可能正在决定是否为团队项目使用Angular,React或Backbone。 所有这些解决方案都以不同的方式解决了相同的问题。

Given this, it’s hard to say there is a single “right” or “best” answer to these problems. But it is possible to say there are “better” or “worse” answers to a given problem.

鉴于此,很难说对这些问题有一个“正确”或“最佳”答案。 但是可以说,对于给定的问题有“更好”或“更差”的答案。

Using one of our previous examples, it might be better to use React for a team project if half your team has experience with it, so it’ll take less time to get up and running.

使用我们之前的示例之一,如果您的团队有一半的经验,将React用于团队项目可能会更好,因此启动和运行将花费更少的时间。

The ability to describe a better solution usually springs from some semblance of time complexity analysis.

描述更好的解决方案的能力通常源于某种时间复杂度分析。

In short, if you’re going to solve a problem, solve it well. And use some Big-O to help you figure out how.

简而言之,如果您要解决问题,请很好地解决。 并使用一些Big-O来帮助您找出方法。

Here’s a final recap:

这是最后的总结:

  • O(1) — Constant Time: it only takes a single step for the algorithm to accomplish the task.

    O(1)—恒定时间:算法仅需一步即可完成任务。

  • O(log n) — Logarithmic Time: The number of steps it takes to accomplish a task are decreased by some factor with each step.

    O(log n)-对数时间:完成一项任务所需要执行的步骤数,每一步都会减少一些。

  • O(n) — Linear Time: The number of of steps required are directly related (1 to 1).

    O(n)—线性时间:所需步骤数直接相关(1到1)。

  • O(n²) — Quadratic Time: The number of steps it takes to accomplish a task is square of n.

    O(n²)—二次时间:完成一项任务所需的步骤数为n的平方。

  • O(C^n) — Exponential: The number of steps it takes to accomplish a task is a constant to the n power (pretty large number).

    O(C ^ n)—指数:完成一项任务所需的步骤数是n次幂的常数(非常大的数字)。

And here are some helpful resources to learn more:

以下是一些有用的资源,以了解更多信息:

  • Wikipedia

    维基百科

  • The Big O Cheat Sheet is a great resource with common algorithmic time complexities and a graphical representation. Check it out!

    Big O备忘单是一个很好的资源,具有常见的算法时间复杂度和图形表示形式。 看看这个!

翻译自: https://www.freecodecamp.org/news/time-is-complex-but-priceless-f0abd015063c/

算法复杂度的表示法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396311.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio 开始运行错误

/********************************************************************************* Android Studio 开始运行错误* 说明&#xff1a;* 打开Android Studio就抛出这个错误。* * 2017-4-1 深圳 南…

IOS 计步器

这篇博客介绍的是当前比较流行的“计步器”-只是简单的知识点 计步器的实现在IOS8开始进行了改变。 但是我会对之前之后的都进行简单介绍。 IOS 8 - // // ViewController.m // CX 计步器 // // Created by ma c on 16/4/12. // Copyright © 2016年 bjsxt. All rights…

vue学习之二ECMAScript6标准

一、ECMAScript6标准简述 ECMAScript 6.0&#xff08;以下简称 ES6&#xff09;是 JavaScript 语言的下一代标准&#xff0c;已经在 2015 年 6 月正式发布了。它的目标&#xff0c;是使得 JavaScript 语言可以用来编写复杂的大型应用程序&#xff0c;成为企业级开发语言。 1.1E…

抖音吸粉_抖音吸粉5大实用方法首次分享!轻松实现粉丝10000+

抖音&#xff0c;是一款可以拍短视频的音乐创意短视频社交软件&#xff0c;该软件于2016年9月上线&#xff0c;是一个专注年轻人音乐短视频社区。用户可以通过这款软件选择歌曲&#xff0c;拍摄音乐短视频&#xff0c;形成自己的作品。抖音APP仅推出半年&#xff0c;用户量就突…

mapper mysql 主键_实现通用mapper主键策略兼容mysql和oracle

【原创文章&#xff0c;转载请注明原文章地址&#xff0c;谢谢&#xff01;】1.直接用官方提供的注解方法是无法达到兼容效果的2.跟踪源码看看是否有其他方法3.这里有个genSql&#xff0c;可以看一下这个类4.创建一个自定义的处理类实现GenSql(代码中是我实际项目中用到的策略&…

权限分配界面 纯手工 仅用到bootstrap的架构 以及 c标签

<div class"form-group"> <div class"row"> <label class"col-sm-2 control-label">配置权限</label> <div class"col-sm-10"> <c:forEach var"m" items…

数据管理与数据库 大学课程_根据数据显示的50种最佳免费在线大学课程

数据管理与数据库 大学课程When I launched Class Central back in November 2011, there were around 18 or so free online courses, and almost all of them were from Stanford.当我在2011年11月推出Class Central时&#xff0c;大约有18项免费在线课程&#xff0c;几乎所有…

每天一个linux命令(12):more命令

more命令&#xff0c;功能类似 cat &#xff0c;cat命令是整个文件的内容从上到下显示在屏幕上。 more会以一页一页的显示方便使用者逐页阅读&#xff0c;而最基本的指令就是按空白键&#xff08;space&#xff09;就往下一页显示&#xff0c;按 b 键就会往回&#xff08;back&…

java 面试题 由浅入深_面试官由浅入深的面试套路

阅读文本大概需要3分钟。从上图看来面试官面试是有套路的&#xff0c;一不小心就一直被套路。0x01&#xff1a;Thread面试官&#xff1a;创建线程有哪几种方式&#xff1f;应聘者&#xff1a;继承Thread类、实现Runable接口、使用j.u.c中的线程池面试官&#xff1a;继承Thread类…

怎么用centos7运行c语言程序_centos如何编译c语言代码

centos如何编译c语言代码,文件,选项,作用,链接,程序 centos如何编译c语言代码 易采站长站,站长之家为您整理了centos如何编译c语言代码的相关内容。 编译c,c++代码 安装gcc 1、使用如下命令查询 centos 官方gcc的所有包:yum -list gcc* 可安装的软件包gcc.x86_64gcc-c++.x86…

第四篇:基本数据类型及用法(1)

字符串&#xff08;str型&#xff09; -可以做加法&#xff0c;乘法 乘法例&#xff1a; n1"alex" n2n1*3 print(n2) #结果&#xff1a;alexalexalex -首字母大写: capitalize() -所有字母变小写: casefold()、lower() #casefold更牛&#xff0c;很多未知的对应关系也…

Android Studio 错误集

错误列表与解决方案: 1.Android studio Gradle project sync failed Android studio 构建项目出错 Error:Unable to start the daemon process: could not reserve enough space for object heap.Please assign more memory to Gradle in the projects gradle.properties file.…

需求简报_代码简报:我如何通过做自己喜欢的事情来获得顶级技术实习

需求简报Here are three stories we published this week that are worth your time:这是我们本周发布的三个值得您关注的故事&#xff1a; How I landed a top-tier tech internship by doing something I love: 7 minute read 我如何通过做自己喜欢的事情获得一流的技术实习…

review what i studied `date` - 2017-3-31

在11 月份内&#xff0c;每天的早上6 点到12 点中&#xff0c;每隔2 小时执行一次/usr/bin/httpd.sh 怎么实现0 6-12/2 * 11 * /usr/bin/httpd.shNginx中的ip_hash是指讲一个地址的请求永久分发至后端的一台RealServer&#xff0c;直至这台RealServer宕机Zabbix和Nagios的工作原…

java string转long报错_java.lang.Integer cannot be cast to java.lang.Long解决办法

你好我是辰兮&#xff0c;本次是项目遇到的java.lang.Integer cannot be cast to java.lang.Long异常以及相对应的解决方案。文章目录一、实战问题用postman测试数据报错&#xff0c;类型转换异常&#xff01;如何将Integer类型转换成长整形 &#xff1f;先转成String型&#x…

pyqt 界面关闭信号_木辛老师的编程课堂之Python和Qt实战慕课软件开发:增加关闭按钮...

软件实战开始&#xff0c;快速提供编程能力&#xff1b;通过实战&#xff0c;分析产品需求&#xff0c;梳理设计需求&#xff0c;提升项目分析和架构的能力。快点跟着木辛老师一起学习吧&#xff01;请点击右上角“关注”按钮关注我们哟&#xff1a;跟着木辛老师学习Python编程…

从零开始nodejs系列文章

http://blog.fens.me/series-nodejs/转载于:https://www.cnblogs.com/chinafbi/p/5394482.html

Leetcode589.N-ary Tree Preorder TraversalN叉树的前序遍历

给定一个 N 叉树&#xff0c;返回其节点值的前序遍历。 class Node { public:int val;vector<Node*> children;Node() {}Node(int _val, vector<Node*> _children) {val _val;children _children;} };//递归 class Solution { public:vector<int> res;vect…

打破双亲委派么,怎么打破_质量保证被打破。 这就是我们如何使其像其他所有东西一样敏捷。...

打破双亲委派么,怎么打破by Derwin由Derwin 质量保证被打破。 这就是我们如何使其像其他所有东西一样敏捷。 (Quality Assurance is broken. Here’s how we can make it as agile as everything else.) Process is the key to great software.过程是出色软件的关键。 In gen…

android java.lang.linkageerror_使用eclipse中的maven构建web应用出现 java.lang.LinkageError异常...

▒▒▒▒: Servlet.service() for servlet [jsp] in context with path [/webdemo] threw exception [java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/jasper/servlet/JasperLoader) previously initiated loading for a different typ…