一起手写吧!数组去重、数组乱序!

数组去重

双循环去重

双重for(或while)循环是比较笨拙的方法,它实现的原理很简单:

先定义一个包含原始数组第一个元素的数组,然后遍历原始数组,将原始数组中的每个元素与新数组中的每个元素进行比对。

如果不重复则添加到新数组中,最后返回新数组;因为它的时间复杂度是O(n^2),如果数组长度很大,那么将会非常耗费内存。 

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    let res = [arr[0]]
    for (let i = 1; i < arr.length; i++) {
        let flag = true
        for (let j = 0; j < res.length; j++) {
            if (arr[i] === res[j]) {
                flag = false;
                break
            }
        }
        if (flag) {
            res.push(arr[i])
        }
    }
    return res
}

set与解构赋值去重

 ES6中新增了数据类型set,set的一个最大的特点就是数据不重复。

Set函数可以接受一个数组(或类数组对象)作为参数来初始化,利用该特性也能做到给数组去重。

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    return [...new Set(arr)]
}

Array.from与set去重

 Array.from方法可以将Set结构转换为数组结果,而我们知道set结果是不重复的数据集,因此能够达到去重的目的

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    return Array.from(new Set(arr))
}

数组乱序

8在处理sort方法时,使用了插入排序和快排两种方案。 当目标数组长度小于10时,使用插入排序;反之,使用快速排序。

其实不管用什么排序方法,大多数排序算法的时间复杂度介于O(n)到O(n²)之间, 元素之间的比较次数通常情况下要远小于n(n-1)/2。

也就意味着有一些元素之间根本就没机会相比较(也就没有了随机交换的可能), 这些 sort 随机排序的算法自然也不能真正随机。

其实我们想使用array.sort进行乱序,理想的方案或者说纯乱序的方案是数组中每两个元素都要进行比较, 这个比较有50%的交换位置概率。

这样一来,总共比较次数一定为n(n-1)。 而在sort排序算法中,大多数情况都不会满足这样的条件。因而当然不是完全随机的结果了。

Fisher–Yates

 因为这个算法是由 Ronald Fisher 和 Frank Yates 首次提出的。

这个算法其实非常的简单,就是将数组从后向前遍历,然后将当前元素与随机位置的元素进行交换。结合图片来解释一下:

首先我们有一个已经排好序的数组

 

Step1: 第一步需要做的就是,从数组末尾开始,选取最后一个元素。

 

在数组一共9个位置中,随机产生一个位置,该位置元素与最后一个元素进行交换。

 

Step2: 上一步中,我们已经把数组末尾元素进行随机置换。 接下来,对数组倒数第二个元素动手。

在除去已经排好的最后一个元素位置以外的8个位置中, 随机产生一个位置,该位置元素与倒数第二个元素进行交换。

Step3: 理解了前两步,接下来就是依次进行。

 

 实现代码如下

function shuffle(arr) {
    let m = arr.length;
    while (m > 1){
        let index = Math.floor(Math.random() * m--);
        [arr[m] , arr[index]] = [arr[index] , arr[m]]
    }
    return arr;
}

从表格中我们可以看出,每个元素在每个位置出现的次数相差不大,说明这种方式满足了随机性的要求。

而且 Fisher–Yates 算法只需要通过一次遍历即可将数组随机打乱顺序,性能极为优异~~

至此,我们找到了将数组乱序操作的最优办法:Fisher–Yates~

原文地址:https://www.cnblogs.com/magicg/p/12710013.html