【面试】数组操作

109 阅读3分钟

题目一 数组乱序

思路

随机选择一个0到len之间的index,将其与0位元素交换,计算交换过的元素个数,下次除去第一个元素后再次随机选择一个index,不断选择,直到所有的元素都遍历过为止。

知识点:

Math.random(): 获取[0-1)之间的随机数

  1. 获得[0-10)之间的随机数:Math.random() * 10
  2. 获取[0-len)之间的随机数: Math.random() * len
  3. 获取[1-10]之间的随机数: Math.random() * 10 + 1
  4. 获取[2-6)之间的随机数:Math.random() * (6-2) + 2

这道题容易出问题的点就是随机index的获取

  1. math.random()取的是带小数点的,需要用Math.floor来向下取整。
  2. 获取[a-b)之间的随机数:Math.random() * (b-a) + a
function shuffle(arr) {
    const len = arr.length;
    let count = 0;
    while (count < len) {
        const index = Math.floor(Math.random() * (len - count) + count);
        [arr[count], arr[index]] = [arr[index], arr[count]];
        count++;
    }
    return arr;
}

function shuttle(arr) {
    const len = arr.length;
    for (let i = 1; i < len; i++) {
        const index = Math.floor(Math.random() * (len - i) + i);
        [arr[i], arr[j]] = [arr[j], arr[i]];
    }
    return arr;
}

function shuttle(arr) {
    const len = arr.length;
    for (let i = 0; i < len - i; i++) {
        const randomIndex = Math.floor(Math.random() * i);
        [arr[randomIndex], arr[len - i - 1]] = [arr[len - i - 1], arr[randomIndex]];
    }
    return arr;
}

shuffle([1, 2, 3, 4]);

题目二 数组扁平化

方法1 递归调用

遍历数组元素,如果当前元素是数组类型,则递归调用,并将结果拼接起来,如果不是,则push到数组中,最后返回结果。

function flatten(arr) {
    let result = [];
    for (let i = 0; i < arr.length; i++) {
        let item = arr[i];
        if (Array.isArray(item)) {
            result = result.concat(flatten(item));
        } else {
            result.push(item);
        }
    }
    return result;
}

flatten([1, 2, 3, [4, 5, 6, [7, [8, 9]]]])

如果借助reduce实现

function flatten(arr) {
    return arr.reduce((acc, cur) => {
        return acc.concat(Array.isArray(cur) ? flatten(cur) : [cur]);
    }, []);
}
flatten([1, 2, 3, [4, 5, 6, [7, [8, 9]]]])

如果传入一个depth参数,代表展开多少层,则如下:

function flatten(arr, depth = Infinity) {
    return arr.reduce((acc, cur) => {
        return acc.concat(Array.isArray(cur) && depth > 0 ? flatten(cur, depth - 1) : [cur])
    }, []);
}

方法2 借助toString方法

数组的toString会把数组转化为以逗号分隔的字符串,然后再调用split转化为数组

function flatten(arr) {
    return arr.toString().split(',').map(item => +item)
}
flatten([1, 2, 3, [4, 5, 6, [7, [8, 9]]]])

方法3 直接调用es6的flat方法

带有一个可选参数,depth,默认为1,如果要全部展开,传入Infinity

function flatten(arr) {
    return arr.flat(Infinity);
}
flatten([1, 2, 3, [4, 5, 6, [7, [8, 9]]]])

方法4 generator方式

没想到吧,还有这种方式

// 生成器函数生成一系列值,然后遍历取值
function *flatten(arr) {
    for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
            yield* flatten(arr[i]);
        } else {
            yield arr[i];
        }
    }
}

let result = [];
for (let f of flatten(arr)) {
    console.log(f);
    result.push(f);
}

题目三 去除数组的重复元素

方法1 双指针法

数组排序,排序之后重复的元素一定是相邻的。

j不断往后遍历,i指向不重复元素的最后一个,

如果i和j对应的元素不相等,j放到i+1的位置,并且i++,j++,否则j++

function removeDuplicate(arr) {
    arr.sort((a, b) => a - b);
    const len = arr.length;
    let i = 0;
    for (let j = 1; i < len && j < len; j++) {
        if (arr[i] !== arr[j]) {
            arr[i+1] = arr[j];
            i++;
        }
    }
    return arr.slice(0, i + 1);
}

方法2 set

[...new Set(arr)]

题目四 push实现

Array.prototype.push = function () {
    for (let i = 0; i < arguments.length; i++) {
        this[this.length] = arguments[i];
    }
    return this.length;
}

题目五 filter实现

Array.prototype.filter = function(fn) {
    let result = [];
    for (let i = 0; i < this.length; i++) {
        if (fn(this[i])) {
            result.push(this[i])
        }
    }
    return result;
}