上学时的数学课会介绍很多定理、公式,但是少有介绍在日常生活中运用的案例。任何一个设计模式、算法都应该是从生活中来,又可以回到生活中去。最近一直在做异常检测与故障诊断相关的事情,越来越觉得算法的重要性,这里记录一下,最近学习的一些常用算法与应用场景。尽量描述的短小、通俗。
大O表示法的理解
大O表示法指出了算法在最坏情况下的运行时间。
几种常见的算法运行时间如下:
- O(logn),也叫对数时间,这样的算法包括二分查找。
- O(n),也叫线性时间,这样的算法包括简单查找。
- O(n*logn),这样的算法包括第4章将介绍的快速排序——一种速度较快的排序算法。
- O(n^2 ),这样的算法包括第2章将介绍的选择排序——一种速度较慢的排序算法。
- O(n!),这样的算法包括接下来将介绍的旅行商问题的解决方案——一种非常慢的算法。
主要启示:
- 算法的速度指的并非时间,而是操作数的增速。
- 谈论算法的速度时,我们说的是随着输入的增加,其运行时间将以什么样的速度增加。
- 算法的运行时间用大O表示法表示。
- O(logn)比O(n)快,当需要搜索的元素越多时,前者比后者快得越多。
查找的前提-排序
日常生活中,我们会有大量的场景去查找东西,比如:查字典,查电话簿,查商品。如果查询的数据集可以以某种形式进行排序,在有序的数据集中进行查找,将大大提高我们的查询速度,人是这样,计算机同样是这样。
排序相关的数据结构-数组与链表的特点:
- 链表的元素是分开的,其中每个元素都存储了下一个元素的地址。
- 数组的读取速度很快。
- 链表的插入和删除速度很快。
选择排序
场景:老师给班级学生的英语成绩进行排序。最直观的排序方式是,每次在原始集合中找出最大的,然后放到新集合中,依次将原始集合中的数据都遍历一遍。它的算法运行时间为O(n^2).
事例代码在这里
快排的前提-递归
递归指的是调用自己的函数,递归操作被广泛的使用在很多算法中,它是我们高中数学中归纳证明在计算机中的应用。递归很可能性能没有多写几个循环来的高,但是它使我们的程序通俗易懂,我们需要在两者之间取得一个平衡。在使用递归时,需要特别注意基线条件:退出递归的条件。计算机在调用函数时都会使用栈这个数据结构,每当你调用函数时,计算机都像这样将函数调用涉及的所有变量的值存储到内存中。如果基线条件没有控制好,很容易造成栈溢出。
在使用递归时,你可能看不到循环操作,其实对栈的后进先出(LIFO)操作隐藏了一个循环操作。存储详尽的信息可能占用大量的内存。每个函数调用都要占用一定的内存,如果栈很高,就意味着计算机存储了大量函数调用的信息。在这种情况下,你有两种选择:
- 重新编写代码,转而使用循环。
- 使用尾递归。而并非所有的语言都支持尾递归。
快速排序
快速排序是远快于选择排序的排序方式,它使用到了递归,基线条件是数组为空或只包含一个元素。在这种情况下,只需原样返回数组,不用排序。快速排序需要经历下面的步骤:
- 选择基准值。
- 将数组分成两个子数组:小于基准值的元素和大于基准值的元素。
- 对这两个子数组进行排序。
Java8代码事例如下:
作者:Kungfu猫熊
链接:https://www.jianshu.com/p/59cfd5cfdf1e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。