【第21题】数组随机排序的三种方法

712 阅读2分钟

题目描述

给定一个数组,对其进行随机排序。示例如下:

// 示例
输入:[0, 2, 4, 8, 1, 3, 5, 8]

// 因为是随机排序,输出结果不唯一
输出:[3, 0, 4, 5, 8, 2, 8, 1]

答案解析

这道题目在面试中也是常考的,变相考察思维逻辑、数组操作API的熟练程度等方面,题目难度为Easy。

我能想到的应用场景就是:接口返回若干道题目,希望每次进入页面,题目的展示顺序是随机的。

下面用三种方法,实现数组随机排序,三种方法各有优劣,涉及的知识点也有所不同。

1. 利用数组自带的sort方法

let ary = [0, 2, 4, 8, 1, 3, 5, 8];
function order(ary) {
    let cloneAry = ary.concat();
    cloneAry.sort((a, b) => {
        return Math.random() - 0.5
    })
    return cloneAry;
}

这种方法是利用随机出一个正数或者负数来让数组里面的内容两两对比,是正数就是顺序,是负数则是倒序,这种方法的缺点就是随机性不高,不能完全随机,因为是两两对比,所以最后一个数在最后的可能性较大。

2. 利用循环遍历

let ary = [0, 2, 4, 8, 1, 3, 5, 8];
function order(ary) {
    let cloneAry = ary.concat();
    let result = [];
    
    while(cloneAry.length > 0) {
        let index = Math.floor(Math.random() * cloneAry.length);
        let item = cloneAry.splice(index, 1);
        result.push(item);
    }
    return result;
}

这种方法定义一个随机数index(因为定了向下取整,所以范围为0~ary.length)作为随机下标,然后将它对应的数从数组中取下压入到result数组中,从而实现随机排序,如果cloneArr的长度为空的话,则退出循环,这种随机的随机性很好,但是代码新创建了一个数组,空间复杂度较高。

3. 洗牌算法(推荐)

let ary = [0, 2, 4, 8, 1, 3, 5, 8];
function order(ary) {
    let cloneAry = ary.concat();
    let len = cloneAry.length;
    for(let i = 0; i < len; i++) {
        let index = Math.floor(Math.random() * cloneAry.length);
        [cloneAry[i], clone[index]] = [cloneAry[index], clone[i]]
    }
    return cloneAry;
}

洗牌算法呢是利用随机出的index下标对应的数,与数组从前到后相互切换,所以称为洗牌,代码运行效率相比前面几种高,随机性也很大,空间复杂度也较低。

关注我

扫一扫 关注我的公众号【前端名狮】,更多精彩内容陪伴你!