LeetCode每日一题,1122. Relative Sort Array
先看题目描述
大意就是有两个数组 arr2 和 arr1,arr2 中没有重复数字,让我们对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾
算法和思路
重写排序规则
由于数组 arr 2 规定了比较顺序,因此我们可以使用哈希表对该顺序进行映射:即对于数组 arr2 中的第 i 个元素,我们将 (arr2[i], i) 这一键值对放入哈希表 map 中,就可以很方便地对数组 arr1 中的元素进行比较
然后就重写排序规则就可以:
- 若 x 和 y 都在哈希表中,则对应值较大的那个排后面
- 若 x 和 y 都不在哈希表中,则本身值较大的那个排后面
- 其他情况下,则不在哈希表中的那个排后面
计数排序
具体地,我们使用一个长度为1 001(下标从 0 到 1000)的数组 counts,记录每一个元素在数组 arr1 中出现的次数。随后我们遍历数 arr2,当遍历到元素 x 时,我们将 counts[x] 个 x 加入答案中,并将 counts[x] 清零。当遍历结束后,arr2 中出现过的元素就已经有序了。
对于剩下的没在 arr2 中出现过的元素,我们只需再遍历一次数组 counts,当遍历到 counts[x] > 0 时,将 counts[x] 个 x 添加到 ans 数组后面。当遍历结束后,没在 arr2 中出现过的元素已按照升序排列在 ans 数组最后,返回 ans 数组即可
算法源码
重写排序规则
由于 java 中的 Arrays.sort() 不能对 int 数组重写排序规则,所有得先把数组转化为列表,再按新的规则排序,然后再把 list 转回数组并返回,操作比较耗时,运行效率不高
1 | import java.util.*; |
计数排序
下面是自己一开始实现的计数排序代码,由于没想到可以在遍历 arr2 时把 counts[x] 清零的操作,所以在最后遍历 counts 数组时使用了一个 HashSet 来判断元素是否出现在 arr2 中,效率比采取清零操作的代码会低一些
1 | import java.util.*; |
下面是在遍历数组 arr2 时使用了清零操作的代码,事实上这个算法的空间复杂度还可以优化,这里定义的 counts 数组长度是 1001,我们可以找出 arr1 数组中元素的最大值 max,然后定义 counts 数组的长度为 max + 1(下标为 0 到 max)即可
1 | import java.util.*; |