题目:如何实现数组去重?
假设有数组 array = [1,5,2,3,4,2,3,1,3,4]
你要写一个函数 unique,使得
unique(array) 的值为 [1,5,2,3,4]
也就是把重复的值都去掉,只保留不重复的值。
方法1:利用indexOf
function uniqueByIndexOf(array) {
var tempArray = [];
for (let i = 0; i < array.length; i++) {
if (tempArray.indexOf(array[i]) === -1) {
tempArray.push(array[i]);
}
}
return tempArray;
}
算法分析
indexOf本身是一个单层循环操作,所以uniqueByIndexOf函数的算法实际上是一个双层循环,因此算法的时间复杂度是O(n²),运行速度不快;在空间上,该算法额外引入了数组对象tempArray,开辟了新内存空间。
方法2:利用Set
function uniqueBySet(array) {
const s = new Set();
array.forEach(item => s.add(item));
return Array.from(s);
}
算法分析:
Set是ES6提供的新数据结构,它类似于数组,但是成员的值都是唯一的,没有重复的值。
由于Set还是基于数组的数据结构,因此uniqueBySet函数的算法和uniqueByIndexOf一样都是双重循环,算法的时间复杂度是O(n²),运行速度不快;在空间上,该算法额外引入了Set对象s,开辟了新内存空间。
方法3:利用Map
function uniqueByMap(array) {
const m = new Map();
for (let i = 0; i < array.length; i++) {
if (!m.has(array[i])) {
m.set(array[i], 0);
}
}
return [...m.keys()];
}
算法分析:
Map也是ES6提供的新数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
由于Map是基于hash的数据结构,查找(has)和插入(set)操作的时间复杂度都是O(1),所以uniqueByMap算法的时间复杂度是O(n),是本文3个算法中效率最高的算法。
在空间上,该算法额外引入了Map对象m,开辟了新内存空间。Map在程序运行时会比数组和Set占用更多的内存,可以算作是uniqueByMap算法的一个小小的缺点。