前端笔试题——手撕快速排序(保姆级手撕)

引言:

许多互联网公司在招聘前端开发人才时,不只考察面试者对于前端知识的掌握程度,数据结构与算法也渐渐成为了默许的要求。html

除了考察链表、二叉树、图等数据结构之外,在算法中最具备表明性的就是“手撕”快速排序算法。前端

快速排序算法,对于大多数人而言确实具备必定的难度。排序思路,代码设计以及难以理解的递归思想。面试

本文一步步带你写基于原生JavaScript语言的快速排序算法。算法

思想:

快速排序最核心的是分治思想,顾名思义,分而治之。数组

简单来讲就是,按照一个标准(也称基准),将一个集合划分为多个集合,分开求解。数据结构

再通俗一点就是,将强大的敌军分红一块一块的,再逐个击破。函数

举个例子:ui

这个数组是乱序的。如今咱们模拟快速排序的过程。spa

首先第一趟是这样的:设计

1.咱们规定基准是当前数组第一个元素,也就是array[0]。

2.将当前数组遍历,比基准小的放left里,大的放right里。

3.一趟完成时,array会被划分为left、mid和right三部分。

如图所示:没有比mid小的元素,因此left数组里是空的;除mid外,其余比mid值大的元素全在right里。

 

 

第二趟也是一样的道理:

1.对于left数组为空,则忽略。

2.对于right数组,里边的元素数量不止一个,那么就能够进行第二趟快排了:

接着再对left和right分别进行划分,快排,宏观看来就是这样:

这种结构是否是很是熟悉,有点像二叉树呢?

设计与实现:

咱们搞懂了过程,如今咱们须要设计算法了。

在笔试中须要手撕快排,最好的办法就是尽可能精简代码,写着也容易,看着也舒服!

根据前边咱们看到的结构,是否是可以联想到二叉树的遍历呢?

二叉树遍历最精简的代码就是使用递归。(无论先序、中序仍是后序)

说白了,递归就是在函数中调用本身,返回本身。

但最重要的仍是要有个终止条件,也就是当数组中的元素数量不大于一个时,就不必排序了。

不管怎样,先定义个quickSort方法:

function quickSort(arr) {
    if (arr.length <= 1) {
        return arr;
    }
}

而后咱们还须要定义数组left和right,还要将mid初始化为arr[0]。

function quickSort(arr) {
    if (arr.length <= 1) {
        return arr;
    }
    let left = [];
    let right = [];
    let mid = arr[0];
}

这时咱们就要遍历数组了,从mid后边的元素开始。

若第i个元素比mid小,就放到left中。

若第i个元素比mid大或者同样大,就放到right中。

因此,上代码:

function quickSort(arr) {
    if (arr.length <= 1) {
        return arr;
    }
    let left = [];
    let right = [];
    let mid = arr[0];
    for (let i = 1; i < arr.length; i++) {
        if (arr[i] < mid) {
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }
    }
}

这样,第一趟排序的结果就能够知道了,咱们用js的concat方法将left、mid和right拼接一下。

function quickSort(arr) {
    if (arr.length <= 1) {
        return arr;
    }
    let left = [];
    let right = [];
    let mid = arr[0];
    for (let i = 1; i < arr.length; i++) {
        if (arr[i] < mid) {
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }
    }
    return left.concat(mid, right);
}

咱们运行一下,看结果:

咱们用流程推理一下,果真是第一趟排序的结果。

接下来,咱们须要进行第二趟、第三趟……最后一趟排序。

这时咱们就要用到递归思想了,咱们须要对left和right再进行quickSort方法的调用。

那么显而易见,这么写就瓜熟蒂落了:

function quickSort(arr) {
    if (arr.length <= 1) {
        return arr;
    }
    let left = [];
    let right = [];
    let mid = arr[0];
    for (let i = 1; i < arr.length; i++) {
        if (arr[i] < mid) {
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }
    }
    return quickSort(left).concat(mid, quickSort(right));
}

好了,这个方法写完了,一切都是那么合理,咱们调用一下看看结果:

console.log(quickSort([1, 5, 2, 3, 6, 8, 8, 7, 4]));

和想象中的同样,一切都在计划中:

至此,快速排序就写完了,至少在笔试中这么写足够用了!

分析:

对于快速排序,平均状况的时间复杂度为:O(n*lgn)。

当一个序列基本有序,就个别一个元素位置不对,那么也就是快速排序算法的最差状况,时间复杂度为:O(n*n)。

因此,与其余排序算法相比,快速排序的性价比仍是最高的,所以使用也最普遍。

原创地址:http://www.javashuo.com/article/p-mcydpnpn-hz.html

相关文章
相关标签/搜索