不管全世界所有人怎么说,我都认为自己的感受才是正确的。无论别人怎么看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎么也长久不了。
LeetCode:原题地址
题目要求
给你两个数组,arr1 和 arr2,arr2 中的元素各不相同,arr2 中的每个元素都出现在 arr1 中。
对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。
示例 1:
输入:arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
输出:[2,2,2,1,4,3,3,9,6,7,19]
示例 2:
输入: arr1 = [28,6,22,8,44,17], arr2 = [22,28,8,6]
输出: [22,28,8,6,17,44]
提示:
- 1 <= arr1.length, arr2.length <= 1000
- 0 <= arr1[i], arr2[i] <= 1000
- arr2 中的元素 arr2[i] 各不相同
- arr2 中的每个元素 arr2[i] 都出现在 arr1 中
思路
-
按 arr2 推入(需要一次遍历)
-
连续重复数字有几个—— 根据 arr1 统计出现次数,放在 counts 容器(一次遍历)
-
剩余数字,把目光投向 counts 容器 (一次遍历)
-
如果是建 map,则遍历 map 中值非0的 key,是无序的,还要 sort。
-
我们开一个容量 1001 的数组 counts,它不止承载出现次数的信息,还承载数字大小的信息。
-
因为数字作为索引存进去,索引就是升序排的。即「计数排序」,用空间换取时间。
var relativeSortArray = function (arr1, arr2) {
const counts = new Array(1001).fill(0);
for (const n of arr1) { // 统计arr1数字的出现次数
counts[n]++;
}
const res = [];
for (const n of arr2) { // 遍历arr2
while (counts[n] > 0) { // 出现次数>0,循环推入res
res.push(n); // 循环结束时,值变为0
counts[n]--;
}
}
for (let i = 0; i < counts.length; i++) { // 遍历counts
while (counts[i] > 0) { // 非0项的索引 循环推入res
res.push(i);
counts[i]--;
}
}
return res;
};