前端筆試題——手撕快速排序(保姆級手撕)

引言:

許多互聯網公司在招聘前端開發人才時,不只考察面試者對於前端知識的掌握程度,數據結構與算法也漸漸成爲了默許的要求。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

相關文章
相關標籤/搜索