【算法之美】数据结构+算法=程序。
前言
数据结构只是静态的描述了数据元素之间的关系。高效的程序需要在数据结构的基础上设计和选择算法。
高效的程序=恰当的数据结构+合适的算法
算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
一、算法的特性
1、 输入:算法具有0个或多个输入;
2、 输出:算法至少有1个或多个输出;
3、 有穷性:算法在有限的步骤之后会自动结束而不会无限循环;
4、 确定性:算法中的每一步都有确定的含义,不会出现二义性;
5、 可行性:算法的每一步都是可行的;
6、 可读性:算法可读性是最容易被忽视的,要注意,程序是写给人看的,而不是计算机;
二、算法效率的衡量
【时间复杂度】同一个问题可以用不同算法来解决,而一个算法的好坏将影响到程序的执行效率。时间复杂度是一个函数,它定性描述了该算法的运行时间。复杂度越低,程序越高效。
【空间复杂度】(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。占用空间越小,复杂度越低。
三、时间复杂度
时间复杂度常用大O符号表述,即大O表示法。
算法效率严重依赖于操作(Operation)数量,在判断时首先关注操作数量的最高次项,操作数量的估算可以作为时间复杂度的估算。如下的例子:
- O(5) = O(1)
- O(2n + 1) = O(2n) = O(n)
- O(n2 + n + 1) = O(n2)
- O(3n3+1) = O(3n3) = O(n3)
常见的时间复杂度有:
- 常数阶O(1),
- 对数阶O(log2 n),
- 线性阶O(n),
- 线性对数阶O(n log2 n),
- 平方阶O(n^2),
- 立方阶O(n^3)
- k次方阶O(n^K),
- 指数阶O(2^n)。
关系:
随着n的不断增大,时间复杂度不断增大,算法花费时间越多。
时间复杂度的计算:
1、 如果算法的执行时间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数此类算法的时间复杂度是O(1);
2、 当有若干个循环语句时,算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的;
3、 循环不仅与n有关,还与执行循环所满足的判断条件有关;
4、 在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度;
四、空间复杂度
算法的空间复杂度通过计算算法的存储空间实现。
S(n) = O(f(n))
其中,n为问题规模,f(n)为在问题规模为n时所占用存储空间的函数。
计算方法:
1、 忽略常数,用O(1)表示;
2、 递归算法的空间复杂度=递归深度N*每次递归所要的辅助空间;
3、 对于单线程来说,递归有运行时堆栈,求的是递归最深的那一次压栈所耗费的空间的个数,因为递归最深的那一次所耗费的空间足以容纳它所有递归过程;
五、方法
递推法
递推是序列计算机中的一种常用算法。它是按照一定的规律来计算序列中的每个项,通常是通过计算机前面的一些项来得出序列中的指定项的值。其思想是把一个复杂的庞大的计算过程转化为简单过程的多次重复,该算法利用了计算机速度快和不知疲倦的机器特点。
递归法
程序调用自身的编程技巧称为递归(recursion)。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法。递归就是在过程或函数里调用自身; 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
穷举法
穷举法,或称为暴力破解法,其基本思路是:对于要解决的问题,列举出它的所有可能的情况,逐个判断有哪些是符合问题所要求的条件,从而得到问题的解。它也常用于对于密码的破译,即将密码进行逐个推算直到找出真正的密码为止。
贪心算法
贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。
用贪心法设计算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,它省去了为找最优解要穷尽所有可能而必须耗费的大量时间,它采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题, 通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。
分治法
分治法是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
动态规划法
动态规划是一种在数学和计算机科学中使用的,用于求解包含重叠子问题的最优化问题的方法。其基本思想是,将原问题分解为相似的子问题,在求解的过程中通过子问题的解求出原问题的解。
迭代法
迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,跟迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。
分支界限法
分支定界法的基本思想是对有约束条件的最优化问题的所有可行解(数目有限)空间进行搜索。
回溯法
回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
六、总结
1、 算法是为了解决实际问题而设计的;
2、 数据结构是算法需要处理的问题载体;
3、 数据结构与算法相辅相成;
4、 多数情况下,算法执行时所用的时间更令人关注;
5、 如果有必要,可以通过增加空间复杂度来降低时间复杂度,空间换时间;
6、 同理,也可以通过增加时间复杂度来降低空间复杂度,时间换空间;
参考资料:
1、 https://blog.csdn.net/HaloTrriger/article/details/78994122;
2、 https://baike.baidu.com/item/%E7%AE%97%E6%B3%95/209025?fr=aladdin;
我的微信公众号:架构真经(id:gentoo666),分享Java干货,高并发编程,热门技术教程,微服务及分布式技术,架构设计,区块链技术,人工智能,大数据,Java面试题,以及前沿热门资讯等。每日更新哦!
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: