题目
销售主管的任务是出售一系列的物品,其中每个物品都有一个编号。
由于出售具有相同编号的商品会更容易,所以销售主管决定删除一些物品。
现在她知道她最多能删除多少物品,她想知道最终袋子里最少可以包含多少种不同编号的物品。
例如,最开始她有n = 6 个物品,编号为:ids = [1,1,1,2,2,3],她最多可以删除 m = 2 个物品。
如果删除两个物品 1,则剩下的物品 ids = [1,2,2,3],此时她拥有三种不同编号的物品。
如果删除两个物品 2,则剩下的物品 ids = [1,1,1,3],此时她拥有两种不同编号的物品。
如果删除物品 2 和物品 3 各 1个,则剩下的物品 ids = [1,1,1,2],此时她拥有两种不同编号的物品。
我们发现,物品最少可以剩下两种不同的编号,所以你的程序要返回 2。
其中,ids 的大小不超过 10^5
1 ≤ ids[i] ≤ 1000000
1 ≤ m ≤ 100000
样例
输入:
[1,1,1,2,2,3] 2
输出:
2
思路
上述题目文字那么多,我们来简化一下。
假设我们有一个数组中array
,现在删掉数组中的number
个元素,要求数组剩余的元素中,相同的元素越多越好!
也就说,删掉的元素出现的次数越少越好,所以这道题其实是遍历array
数组中的每个元素,统计每个元素出现的次数,然后根据 number
的值来删除次数出现少的元素。
好了,题意明白了,我们直接上代码。
const smartSale1 = (array=[], number=0)=>{
//创建了一个名为 `resultArr` 的空数组,用于存储统计后的元素和数量。
let resultArr = [];
array.forEach( item => {
let obj = {name: item, num: 1};
let i = resultArr.findIndex(element => element.name == item);
//通过 `forEach` 遍历 `array` 中的每个元素,如果 `resultArr` 中不存在当前元素,将其添加到 `resultArr` 中,如果存在当前元素,则元素数量+1
i !== -1 ? resultArr[i].num+=1 : resultArr.push(obj);
});
// 接着,对 `resultArr` 中的每个元素按照数量升序排序。
resultArr.sort((a,b)=>a.num-b.num);
//排序完成,从数量最小的元素开始删除
// 声明一个变量`sum`赋值为0
let sum = 0 ;
for (let index = 0; index < resultArr.length; index++) {
// 从第一个元素开始,把元素的`num`累加给`sum`
sum += resultArr[index].num;
// 当sum大于给定数量number时跳出循环
if(sum > number){
break
}else{
// 当sum小于等于给定数量number时,删除元素,resultArr数组数量减一
resultArr.splice(index,1);
index--
};
};
//函数返回删除元素后 `resultArr` 的长度,也就是上上述题目中剩余物品种类。
return resultArr.length;
};
本来以为上述代码没啥毛病,结果将array
的数组数量放到很多,诸如99000个时,再将number=10000
,此时运行代码,页面则会卡很久才会出结果。
那么,怎么优化此段代码呢?
经搜索发现,用数组来存储元素及其数量可能不是最优选择,而使用数据结构Map
来存储元素及其数量则更高效,尤其是在大数据量时尤为明显,以下是使用 Map
数据结构优化的代码示例:
const smartSale = (array = [], number = 0) => {
let count = new Map();
for (let num of array) {
if (count.has(num)) {
count.set(num, count.get(num) + 1);
} else {
count.set(num, 1);
}
}
let resultArr = Array.from(count.values()).sort((a, b) => a - b);
let sum = 0 ;
for (let index = 0; index < resultArr.length; index++) {
// 从第一个元素开始,把元素的`num`累加给`sum`
sum += resultArr[index];
// 当sum大于给定数量number时跳出循环
if(sum > number){
break
}else{
// 当sum小于等于给定数量number时,删除元素,resultArr数组数量减一
resultArr.splice(index,1);
index--
};
};
return resultArr.length;
};
同等条件下,运行该代码,116.73291015625 ms就得出结果,如图: