剑指 Offer II 075. 数组相对排序(自定义排序、计数排序)
题目描述
方法一:最简单最容易想到的方法
- 用一个
map<int, int> mp
记录arr1
中的每个数字出现的次数 - 遍历
arr2
的同时,向答案数组ans
中循环添加arr2[i]
,循环次数为arr1
中出现的次数,同时用一个变量cnt
记录所有出现的次数总和。即mp[arr2[i]]
,遍历结束时arr1
中出现在arr2
中的数字就有序了 - 用一个
set<int> st
存储arr2
中的数字,遍历arr1
,如果不曾出现在st
中,就添加到答案数组ans
后面; - 到这里,
ans
数组中的前cnt
个数字是已经排好序的, 后面的数字是无序的,只需要将后面的数字排序即可sort(ans.begin() + cnt, ans.end())
。
class Solution {
public:
vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2) {
map<int, int> mp;
set<int> st;
for (int i = 0; i < arr1.size(); i++) {
mp[arr1[i]]++;
}
vector<int> tmp;
int cnt = 0;
for (auto k : arr2) {
st.insert(k);
int n = mp[k];
cnt += n;
while (n--) {
tmp.push_back(k);
}
}
for (auto num : arr1) {
if (st.find(num) == st.end()) {
tmp.push_back(num);
}
}
sort(tmp.begin() + cnt, tmp.end());
return tmp;
}
};
方法二:直接对数组自定义排序
看了题解之后,总结一下。其实可以自定义排序方法,对arr1
直接进行排序。
- 先用一个哈希表
map<int, int> mp
记录arr2
中的所有数字arr2[i]
及其下标位置[i]
,也就是mp[arr2[i]] = [i]
; - 自定义
sort
函数中的比较方法,对于两个元素a、b
:- 如果a、b都在哈希表中,说明a、b都在
arr2
中,那么比较他俩的下标位置,下标小的元素较小; - 如果a、b都不在哈希表中,按正常大小顺序比较;
- 如果一个在哈希表中,一个不在哈希表中,那么在哈希表中的元素较小。
- 如果a、b都在哈希表中,说明a、b都在
- 直接对
arr1
进行排序即可。 - 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)空间复杂度: O ( m ) O(m) O(m)
class Solution {
public:
vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2) {
unordered_map<int, int> mp;
for (int i = 0; i < arr2.size(); i++) {
mp[arr2[i]] = i;
}
sort(arr1.begin(), arr1.end(), [&](const int &a, const int &b) {
if (mp.count(a)) {
return mp.count(b) ? mp[a] < mp[b] : true;
} else {
return mp.count(b) ? false : a < b;
}
});
return arr1;
}
};
方法三:计数排序(对方法一进行优化)
仔细考虑方法一,其实有点像计数排序的思路。用计数排序,不需要使用哈希表来存储元素出现的次数,而是使用一个数组。本题的arr2
数组中元素的最大值不超过1000,所以可以开一个长度为1001的数组来记录每个数字在arr1
中出现的次数,以及arr2
中出现的元素。
- 时间复杂度 O ( n + m + 1001 ) O(n+m+1001) O(n+m+1001),空间复杂度 O ( 1001 ) O(1001) O(1001)
class Solution {
public:
vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2) {
vector<int> freq(1001);
for (auto num : arr1) {
freq[num]++;
}
vector<int> ans;
for (auto num : arr2) {
while (freq[num]) {
ans.push_back(num);
freq[num]--;
}
}
for (int i = 0; i < freq.size(); i++) {
while (freq[i]) {
ans.push_back(i);
freq[i]--;
}
}
return ans;
}
};