小白讲故事,每日都精彩
今日小白将要谈谈社会现象“插队”。
之前看了一个抖音(小白可不是抖音控)。一个小伙纸插队到小姐姐面前,小姐姐拍拍他的肩膀说:“我们熟吗?”。小伙子:“不熟”。小姐姐一脚把小伙子踢开,“不熟,尼玛插什么队”!
小白想告诉那哥们,“来跟小白学习插队的正确方式---插入排序”
插队的正确姿势
假设前面站了一排有序的美女(牌),如何才能接近我们心意的妹子面前呢(要插入的对象)?
那还不简单,直接上去跟妹子说:“妹子,哥看上你了,跟哥回家吧”!
小白多年爱情失败的经验总结出两个字:“套路”!(套路得人心,小白说的)
话不多说,直接看我们如何把问题抽象。
function insert(A, x)
A: 已排序的数组
x: 要插入的元素
我们先想一版最暴力最直接的写法
function insert(A, x){
// 找出第一个大于x的元素
let b = A.find(item => item > x)
// 不存在最大值添加在尾部
if(b == undefined) {
A.push(x)
}else{
// 否则直接插入到当前坐标
const index = A.indexOf(b)
A.splice(index, 0, x)
}
}
这好比第一个哥们追女孩子的方式.既然小白说了套路得人心,我们就设计一套可优化的方案。
之前我们用过循环不变式,这是我们一个重要思想。 假设p是我们要比较的位置,p+1是是我们腾出来的空位置,那么就如下图。
代码部分:
/**
* @description insert
* @params {array} arr 插入数组
* @params {number} i 空位坐标
* @params {number} x 插入对象
*/
function insert(arr, i, x){
let p = i - 1;
while( p>=0 && arr[p] > x){
arr[p+1] = arr[p];
p--;
}
arr[p+1] = x;
}
来看看我们完整插入排序实现方式:
function insert(arr, i, x){
let p = i - 1;
while( p>=0 && arr[p] > x){
arr[p+1] = arr[p];
p--;
}
arr[p+1] = x;
}
function insertion_sort(A){
for(let i=1, len=A.length; i < len; i++){
insert(A, i, A[i])
}
}
插队难度系对比
话说长得好看的小哥哥,可能一次就能插队成功。(最好的情况)
俗话魅力不足,就脚踏实地,死皮赖脸的一次又一次的粘。(最坏情况)
上面说过最好的情况是1次排序成功,从时间复杂度上说是个常数O(c)。
最坏的情况在于insert的内循环,关键取决于i的次数,所以1+2+3+...+N,其他的都是常数。最终得出应该O(n*n)。
最终结果介于O(c)和O(n*n)中间。这个之后会介绍算法的好坏程度。如不懂之后,先略过
每日一题
1
3 5
7 9 11
13 15 17 19
21 23 25 27 29
写一个函数,给定行的序号,然后求和:
rowSumOddNumbers(1) // 1
rowSumOddNumbers(2) // 3+5=8
rowSumOddNumbers(3) // 7+9+11=27
rowSumOddNumbers(42) // 74088