小白都能玩的算法day6-插入排序

377 阅读3分钟

小白讲故事,每日都精彩

今日小白将要谈谈社会现象“插队”。

之前看了一个抖音(小白可不是抖音控)。一个小伙纸插队到小姐姐面前,小姐姐拍拍他的肩膀说:“我们熟吗?”。小伙子:“不熟”。小姐姐一脚把小伙子踢开,“不熟,尼玛插什么队”!

小白想告诉那哥们,“来跟小白学习插队的正确方式---插入排序

插队的正确姿势

假设前面站了一排有序的美女(牌),如何才能接近我们心意的妹子面前呢(要插入的对象)?

那还不简单,直接上去跟妹子说:“妹子,哥看上你了,跟哥回家吧”!

小白多年爱情失败的经验总结出两个字:“套路”!(套路得人心,小白说的)

话不多说,直接看我们如何把问题抽象。

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