文章目录
“ 分治:把问题的范围缩小,把解题的效率提高。”
在生活当中,很多情景会让我们不知不觉使用到搜索,比如说找到家里年龄最大的人是谁,找到一堆纸币中发行时间最久的是哪一张,总之,在日常生活中,不知不觉的也在使用算法去解决一些看似简单的问题。
今天提到的就是通过划分来达到快速选择;查找一个家庭中年龄最大的人,因为基数小,可以快速得到结果,如果扩大基数或者查找范围变化如查找家庭中年龄第3大的人,就需要一些计算才能得到;简单来说,我们需要解决如何快速找到一组元素中的第k个大元素。
有的人可能想到了先排序的方式,虽说排序是一种不错的方式,但是对于时间复杂度来说,快排最理想可以达到o(n * logn),对于简单的查找也有点小题大做。
聊聊lomuto划分
lomuto划分(顺序从小到大)的基本思想是将数组首位作为哨兵位,一次遍历数组,从哨兵位的下一个数字开始查找,当找到比哨兵位小的数字,计数+1,并且交换计数对应数组位置的元素和当前被比较的数字,直到遍历结束,把哨兵位的数字放到计数结果后一位(这个数字前面都是比它小的数)。
也就是说lomuto划分每次操作的是哨兵位的数字,把比哨兵位小的数字全部移到哨兵位之前,把比哨兵位数字大的数字全部移到其之后。
看一组数字的划分过程:
[ 99, 1, 2, 3, 4, 100, 200, 90, 5 ]
从上面的处理过程可以看出,lomuto划分实际每次会查找比哨兵位数字小的数字,然后把比哨兵位小的数字放到这个数字之前,比哨兵位大的数字放到哨兵位之后。
注意:因为lumoto划分每次处理的都是哨兵位的数字,所以如果哨兵位的数字原本对应的位置就是正确的,则通过lomuto划分永远只会有一种效果(不断调用lomuto划分,不做其他操作)。
所以对于lomuto划分,可以得到很简单的代码表达,这是我们实现快速选择第k大数字的第一步:
//参数说明:
//list :数组
//start : 开始比较的数字下标
//end :结束比较的数字下标