解法一:负数
这个题之前就做过类似的,一看题目是负数,这次直接就把右边的映射成负数,左边编码,然后一排序再解码就行了。
class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
start = -len(arr2)-2
encoder, decoder = {}, {}
for num in arr2:
encoder[num] = start
decoder[start] = num
start += 1
for i in range(len(arr1)):
if arr1[i] in encoder:
arr1[i] = encoder[arr1[i]]
arr1.sort()
for i in range(len(arr1)):
if arr1[i] in decoder:
arr1[i] = decoder[arr1[i]]
return arr1
解法二:自定义排序
负数解法有个很大的缺点就是如果数组本来就有负数呢,如果数组最小的负数在越界边缘呢?很麻烦吧想必,所以用哈希表自定义排序方式是一种很好的解法。我们可以通过lambda创建元组的方式来排序。
class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
start = 1
d = {}
for num in arr2:
d[num] = start
start += 1
return sorted(arr1, key=lambda x: (1, x) if x not in d else (0, d[x]))
解法三:计数排序
这是本题最快的做法,无序排序,O(n)即可。方法基于桶排序,用一个特别长(等于数据范围)的数组记录频率,然后扫一遍就行了。其实是个指数级的算法,因为随数据位数增加,时间会呈指数型增长。但本题中确实是最快的。(提交的时候其实也不是很快哈哈)
class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
times = [0 for _ in range(1002)]
result = []
for num in arr1:
times[num] += 1
for num in arr2:
result.extend([num]*times[num])
times[num] = 0
for i in range(1001):
if times[i] > 0:
result.extend([i]*times[i])
return result