白话算法：时间复杂度和大O表示法

所以究竟什么是算法？

``````function 烘烤蛋糕(风味, 加冰){

"
1. 烤箱预热到350度（华氏）
2. 混合面粉、酵母粉、盐
3. 打发黄油和糖直到蓬松

4. 添加鸡蛋
5. 将黄油和鸡蛋混到面粉中
6. 添加牛奶和 " + 风味 + "
7. 继续搅拌
8. 放入盘中
9. 烘烤30分钟
10." 如果要 加冰 ，加点冰 "
10. 大快朵颐
"
}
BakeCake('香草味', 要加冰) => 美味
``````

你会问，什么是大 O 表示法？

``````规律       Big-O

2             O(1)   --> 就是一个常数

2n + 10       O(n)   --> n 对整体结果会产生最大影响

5n^2         O(n^2) --> n^2 具有最大影响
``````

• **O(1)— **常量时间：给定一个大小为n的输入，概算法只需要一步就可以完成任务。

• **O(log n)— **对数时间：给定大小为n的输入，该算法每执行一步，它完成任务所需要的步骤数目会以一定的因子减少。

• **O(n)— **线性时间：给定大小为n的输入，该算法完成任务所需要的步骤直接和n相关（1对1的关系）。

• O(n²)—二次方时间：给定大小为n的输入，完成任务所需要的步骤是n的平方。

• **O(C^n)— **指数时间：给定大小为n的输入，完成任务所需要的步骤是一个常数的n次方（非常大的数字）。

``````let n = 16;

O (1) = 1 step "(awesome!)"

O (log n) = 4 steps "(awesome!)" -- assumed base 2

O (n) = 16 steps "(pretty good!)"
O(n^2) = 256 steps "(uhh..we can work with this?)"
O(2^n) = 65,536 steps "(...)"
``````

``````var friends = {

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

O(1)— 常量时间

``````//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 step
function add(num1,num2){ // I have two numbers, takes one step to return the value
return num1 + num2
}
``````

O (log n)— 对数时间

``````//You decrease the amount of work you have to do with each step

function 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 array
if( 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)— 线性时间

``````

//The number of steps you take is directly correlated to the your input size

var sum = 0;
for (let i=0 ; i < array.length; i++){ //has to go through each value
sum += array[i]
}
return sum;
}
​```

O(n²)— 二次方时间

for循环嵌套的复杂度就是二次方的，因为你在一个线性操作里执行另外一个线性操作（或者说： n*n =n² ）

``````//The number of steps you take is your input size squared

for (let i=0 ; i < array.length; i++){ //has to go through each value
for(let j=i+1 ; j < array.length ; j++){ //and go through them again
}
}
}
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)—指数时间

``````//The number of steps it takes to accomplish a task is a constant to the n power

//实例

//尝试找出长度为n的密码中所以字符的组合
``````

1、这个可以解决问题吗？ =>

2、你有时间考虑时间复杂度吗
=>进入第三步
=>稍后再回来，现在就跳转到第六步

3、它覆盖了所有的边界条件？ =>

4、我的复杂度已经尽可能低？
=>重写或者修改解决方案 -> 回到步骤1
=>进入步骤5

5、我的代码D.R.Y(Don't Repeat Yourself) =>

6、欢呼吧！
=>将代码重构到D.R.Y，然后再欢呼！

• **O(1)— **常数时间：该算法仅仅使用一步就可以完成任务

• **O(log n)— **对数时间：该算法每执行一步，它完成任务所需要的步骤数目会以一定的因子减少。

• **O(n)— **线性时间：该算法完成任务所需要的步骤直接和n相关（1对1的关系）。

• **O(n²)— **二次方时间：完成任务所需要的步骤是n的平方。

• **O(C^n)— **指数时间：完成任务所需要的步骤是一个常数的n次方（非常大的数字）。

• 维基百科

• 大O小抄是一个非常棒的资源，它提供了常用的算法时间复杂度，并以图表的形式呈现。

推荐阅读更多精彩内容

• 通常，对于一个给定的算法，我们要做 两项分析。第一是从数学上证明算法的正确性，这一步主要用到形式化证明的方法及相关...
刚哥说阅读 823评论 0 11
• 算法复杂度 时间复杂度 空间复杂度 什么是时间复杂度 算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗...
KODIE阅读 1,221评论 0 9
• 算法是计算机处理信息的本质，因为计算机程序本质上是一个算法来告诉计算机确切的步骤来执行一个指定的任务。算法是独立存...
LittlePy阅读 680评论 0 0
• 算法的时间复杂度和空间复杂度-总结通常，对于一个给定的算法，我们要做 两项分析。第一是从数学上证明算法的正确性，这...
Explorer_Mi阅读 492评论 0 1
• 文案写手是坐在键盘后面的销售人员。 销售才是广告的目标，将100%的重心，放在如何让读者现身跟你交易。 想要写出有...
童方民阅读 93评论 0 1