现在公司对员工的基本功考验越来越重视,作为底层员工的我们需要平时多练习。35岁之后,如果基本功不扎实,作为底层的码农前途还是很黯淡的。
大家需要平时多练习leetcode上面的题,作为码农来说,还真是马云爸爸说的那样,要么去BAT那样的公司直接加班变现,他们也舍得给钱,算是福报了;很多中小公司变相让你免费加班,待遇却不到BAT的一半都不到。
这里按照平均时间复杂度来进行实现和介绍。
1. 冒泡排序和插入排序
冒泡排序和插入排序都是时间复杂度为 o(n^2)的操作, 都也是稳定的排序。 冒泡排序主要内容是比较和交换, 插入排序主要内容是比较和移位。
冒泡排序:
插入排序:
2. 归并排序和快速排序,堆排序
归并排序和快速排序都,堆排序是时间复杂度为o(n*log2(n))的操作,其中归并排序和堆排序是稳定的排序,快速排序不是稳定的排序。
归并排序是从底到顶的操作,主要内容是将数组从中间一分为二,分解各个部分,直至不能分解,再从底部向上进行各个有序数组段的合并(底部最开始肯定是2个数之间的有序合并),核心是merge函数的编写(合并二个有序数组为一个有序数组,因此需要一个缓存数组)。
快速排序是从顶到底的操作, 主要内容是确定分区点,一般选取数组的最后一个元素作为分区点,将数组分为2部分,左边部分是小于分区点的数据,右边是大于等于分区点的数据,然后在分别对左右二边的数组递归进行排序,核心是 partition函数的编写(确定分区点,并且将数组的元素以分区点的数据为中间位置的数据进行排列)。
堆排序主要AVL(平衡二叉数)来实现,一般来说创建一个没有顺序的二叉树是没有任何实际意义的。
归并排序:
快速排序:
堆排序:
散列表,二叉树,堆都是动态数据结构。 这里需要对某一个数目i的数组构建一个大顶堆,构建后将堆的第一个元素换到最后一个元素位置, 然后对剩下的前面(忽略掉最后一个元素)i-1数组重新构建大顶堆;所以这里从满数组开始构建。针对某一个固定数目的数组,其构建大顶堆的过程,是从其i/2个父母节点开始向前进行构建; 针对某个父母节点的构建过程,是其值与自己的左右孩子的值比较, 保证该父母节点的值是最大的值,如果做了值交换的操作,就影响了该孩子节点所在子树的排序,需要再对该孩子节点重新进行构建。
3. 桶排序,基数排序 和计数排序
桶排序和计数排序,基数排序都是时间复杂度为o(n)得排序。 当然取得这么好的效果,肯定是对数据要有一定得要求的。
桶排序要求数据的取值范围要小于数据本身的数目,通过对数据按照取值范围划分成一个个等份的桶(buket),最好是桶之间已经排好序了,然后对桶内的数据按照快速排序进行排序,最后按照桶的先后顺序读出数据,就是排好序的数据。桶排序适合离线数据排序,且数据为非负数。
计数排序是桶排序的一种变种, 它通过增加一个计数器数组,下标是数据的取值,内容是该取值的计数(实际上存的是该取值计数之前的累计计数),然后 读取计数器数组的值,作为index,该index上的值为计数器数组的对应下标。得到的就是排好序的数组。这里需要考虑数据有重复的情况。
基数排序对数据要求比较高,它要求数据的取值可以划分为各个层级(进制的概念),上一层的取值比较过了,下一层就不用再比较。 同一层级的数据可以使用快速排序来比较。
桶排序:
计数排序:
基数排序: