剑指 Offer II 075. 数组相对排序(自定义排序、计数排序)

剑指 Offer II 075. 数组相对排序(自定义排序、计数排序)

题目描述

截屏2022-02-15 下午2.08.55

方法一:最简单最容易想到的方法

  • 用一个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都不在哈希表中,按正常大小顺序比较;
    • 如果一个在哈希表中,一个不在哈希表中,那么在哈希表中的元素较小。
  • 直接对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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值