leetcode 1122. 数组的相对排序

这篇博客讨论了一种解决对两个数组arr1和arr2中元素相对顺序排序的问题。通过创建哈希表映射arr2的顺序并自定义比较函数,可以使用排序算法实现相对排序。另外,也提到了计数排序的解决方案,尤其适用于元素范围不大的情况,该方法能在O(N)的时间复杂度内完成排序。博客深入分析了两种方法的时间和空间复杂度,并提供了具体的Python代码实现。
摘要由CSDN通过智能技术生成

给你两个数组,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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值