【路飞】算法与数据结构-数组的相对排序

114 阅读1分钟

不管全世界所有人怎么说,我都认为自己的感受才是正确的。无论别人怎么看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎么也长久不了。

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;
};