Algorithm

«漫画算法»是一本偶然间发现的算法书,算是一份意外的收获吧。之前看到的很多书荐,买来都吃灰了也没翻过,这本算法书是第一次看完,小小总结一下。

这本书比较基础,算是入门级的算法书。主要讲解了基本的数据结构和排序算法,还有一些算法的实际应用。主要分为四部分。

  • 第一部分是算法的基本概述
    • 衡量算法的复杂度方式,分别是时间和空间,同时列出了常遇到的时间复杂度的计算。
  • 第二部分是数据的结构构造
    • 数据结构一般有物理结构和逻辑结构,物理结构是在内存中实际存在的结构,有数组和链表两种方式。数组对应查找多的比较有优势,链表对于修改比较多的有优势。链表反过来,对于查找不方便,但是对于插入,删除那些操作改动比较小。其实还有另外一种物理结构,这种是数组的变种-哈希表,这种数据结构主要是为了便于索引,通过对key值的一种计算,定位到数组中的下标去保存数据,这种对于数据的插入和查找都是比较方便的,基本是N(1)的时间复杂度。另外的逻辑结构就是栈,队列,树,图等存储结构。这些逻辑结构都可以用数组或链表这种物理结构来存储,但是作用不一样。栈是一种先进后出的逻辑,主要用来回溯用的。比如有递归逻辑的算法可以转化为用栈调用的方式,栈结构这种方式是为了把先前遍历过的数据用倒序的方式再取出来,类似历史的回溯,从金经历到现在,然后又从现在倒序,先清朝,到明朝,再到金的顺序。队列就不太一样了,队列是先进先出的一种结构,就是经过了那么多朝代,然后又按开始的那个朝代到现在再回放一次。栈和队列有两种比较实际的应用方式,栈用在二叉树的深度遍历上,因为栈需要按照遍历过的顺序再回退遍历另外一边,所以可以应用在这种场景。而队列是用在二叉树的广度遍历上,因为先前入队的元素需要按照顺序再次出来,然后又把出来那个元素的左右子树入队。
  • 第三部分是排序算法
    • 主要有冒泡排序,快速排序,堆排序,基数排序和桶排序。对应的时间复杂度分别是O(n平方),O(nlogn),O(nlogn),O(n + m),O(n)。其中冒泡排序可以用变量去记录每轮是否存在交换,从而减少整体遍历的次数的方式去优化,还有另外可以通过每次遍历都是记录每轮遍历的边界值,然后下一轮遍历的时候可以少遍历些。快速排序也有两种方法,一种是双向遍历的方式,一种是单向遍历。堆排序是通过每次都移除顶点,然后再进行一次修复的过程,所以是O(nlogn)的操作。基数排序是用位相对位置的索引来记录数据出现的次数的算法,然后再按照出现的次数输入对应的数据,这种排序算法主要是用在数据分布比较均匀,相差不大的情况下的。如果相差比较大就要用到桶排序了。
  • 第四部分是面试时候遇到的算法问题
    • 如何判断链表有环:有环代表可以用追及问题去记录环的节点数。可以设定两个指针,然后一直遍历,直到第一次相遇,然后继续行走,直到第二次相遇。
    • 记录栈中最小值:这种是要添加另外一个栈来记录最小值,由于栈有后进先退的特点,所以单纯记录最小值还是不行的,还需要记录连续的最小值。可以假设栈底是最小的元素,然后遇到有比栈底小的元素就放入到最小栈中去,当栈中的最小数出栈时,对应的最小栈也要出栈。这种方式是为了在防止最小值出栈时没办法记录到下一个最小值的情况。
    • 最大公约数:最大公约数用了另外一种技巧,是通过辗转相除或相减的方式去算。
    • 如何判断一个数是否为2的整数次幂:2的整数幂转成二进制是高位为1,其它位为0的情况。这种数减1后变为二进制全为1,这时候与原来的数进行与运算,得出的结果如果是0,则表示那个整数是2的整数次幂。
    • 无序数组排序后的最大相邻差:这种方式是利用基数排序算法排好序,然后统计0连续出现的个数最大的就是最大的相邻差。
    • 如何用栈实现队列:这种算法的思想主要是用两个栈来实现,一个栈是用于正常的入队,在出队列的时候,由于需要先进先出,所以需要倒一下顺序,所以可以把第一个栈中的数据按顺序出栈,放到第二个栈中,这样顺序就倒过来了,这时候出队列就可以在第二个栈中出了。
    • 如何求解金矿问题:金矿问题的最优解其实就是动态规划的问题。描述起来就是对于一个方案选择是先选择或者不选择时的最优解,然后逐层增加个数,逐渐选择最优的情况。
    • 寻找缺失的整数:主要是运用到位运算来统计缺失了什么数,用到了一种常规的算法是分治法,这种方法是先分开,然后再求解。
  • 第五部分是算法的实际应用。
    • bitmap算法:位图元素是用来记录数据是否出现了,这种方式比较省内存,筛选数据比较容易
    • LRU算法:这种算法是为了在内存不够的情况下,可以去掉一些比较少用到的数据
    • A星寻路算法:这种算法是为了找到最短路径的算法