给你两个数组,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]
一种容易想到的方法是使用排序并自定义比较函数。由于数组arr2规定了比较顺序,因此我们可以使用哈希表对该顺序进行映射:即对于数组arr2中的第 i个元素,我们将(arr2[i], i)这一键值对放入哈希表hash 中,就可以很方便地对数组arr1中的元素进行比较。比较函数的写法有很多种,例如我们可以使用最基础的比较方法,对于元素x和y:
如果x和y都出现在哈希表中,那么比较它们对应的值hash(x) 和 hash(y);
如果x和y都没有出现在哈希表中,那么比较它们本身;
对于剩余的情况,出现在哈希表中的那个元素较小。
时间复杂度:O(mlogm + n) 其中m和n分别是数组arr1和arr2的长度。构造哈希表的时间复杂度为n,排序的时间复杂度为mlogm。
空间复杂度:O(logm + n),哈希表需要的空间为n,排序需要的栈空间为logm。
class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
infini = 1e8
hash_table = {}
for i in range(len(arr2)):
hash_table[arr2[i]] = i
def cmp(key):
return hash_table.get(key, infini), key
output = sorted(arr1, key=cmp)
return output
注意到本题中元素的范围为 ,这个范围不是很大,我们也可以考虑不基于比较的排序,例如「计数排序」。具体地,我们使用一个长度为 max-min+1(下标从0到 max-min)的数组C,记录arr1每一个元素出现的次数。随后我们遍历数组arr2,当遍历到元素x时,我们将C[x-min]个x加入答案中,并将C[x-min]清零。当遍历结束后,所有在arr2中出现过的元素就已经有序了。此时还剩下没有在arr2中出现过的元素,因此我们还需要对整个数组arr1进行一次遍历。当遍历到元素x时,如果C[x-min]不为0,我们就将 C[x-min]个x加入答案中。
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
min_value = min(arr1)
max_value = max(arr1)
C = [0 for value in range(max_value - min_value + 1)]
for value in arr1:
C[value - min_value] += 1
output = []
# 时间复杂度O(N), N为arr1的元素个数
for value in arr2:
for i in range(C[value-min_value]):
output.append(value)
C[value-min_value] = 0
for value in range(min_value, max_value+1)::
if C[value-min_value] != 0:
for i in range(C[value-min_value]):
output.append(value)
return output