六月集训(第03天)— 排序

@

排序

1. 1464. 数组中两元素的最大乘积

    思路:
        降序排列,取下标最小的两个数,即为值最大的两个数

class Solution {
    static bool cmp(const int a, const int b) {
        return a > b;
    }
public:
    int maxProduct(vector<int>& nums) {
        sort(nums.begin(), nums.end(), cmp);
        return (nums[0] - 1) * (nums[1] - 1);
    }
};

2. 1636. 按照频率将数组升序排序

    思路:
        按照题目描述进行排序即可。学习一手sort()函数cmp函数的写法。

class Solution {
public:
    vector<int> frequencySort(vector<int>& nums) {
        int hash[205];
        memset(hash, 0, sizeof(hash));
        int nums_size = nums.size();
        for (int i = 0; i < nums_size; ++i) {
            hash[nums[i] + 100] ++;
        }
        sort(nums.begin(), nums.end(), [&](const int &a, const int &b) {
            if (hash[a + 100] != hash[b + 100]) return hash[a + 100] < hash[b + 100];
            return a > b;
        } );
        return nums;
    }
};

3. 1287. 有序数组中出现次数超过25%的元素

    思路:
        由于数组有序,遍历寻找答案即可。

class Solution {
public:
    int findSpecialInteger(vector<int>& arr) {
        int arr_size = arr.size();
        int cnt = 1;
        int ans = arr[0];
        for (int i = 1; i < arr_size; ++i) {
            if (arr[i] == arr[i - 1]) {
                ++cnt;

                if (1.0 * cnt / (1.0 * arr_size) - 0.25 > 1e-8) {
                    ans = arr[i];
                    break;
                }
            } else {
                cnt = 1;
            }
        }
        return ans;
    }
};

4. 436. 寻找右区间

    思路:
数据范围 :1 <= intervals.length <= 2 * 104
        根据数据范围,$O(n^2)$的算法肯定过不了,可以尝试$O(nlog(n))$的算法。
        要找比右边界大的最小的左边的对应的集合。将原数据拷贝一份,分别以左边界和右边界为参考依据升序排序。时间复杂度$O(nlog(n))$
        枚举右边界排序的集合,遍历左边界排序的集合,寻找的一个比右边界大的集合对应的序号即为答案。
        但是上述方法的时间复杂度为$O(n^2)$,那么来优化一下。考虑到两组数据都已经升序排序,那么匹配右边界的第一个左边界之前的集合肯定不能满足大于之后枚举的右边界,所以遍历左边界数据的下标不用从0重新开始,继续向后遍历即可。如此只需要将两组数据各遍历一次就好,时间复杂度降到$2n$,即$O(n)$
        总的时间复杂度为$O(nlog(n) + n)$

class Solution {
public:
    vector<int> findRightInterval(vector<vector<int>>& intervals) {
        int intervals_size = intervals.size();
        vector<int> ans(intervals_size, -1);
        vector<vector<int>> intervals_right;
        for (int i = 0; i < intervals_size; ++i) {
            intervals[i].push_back(i);	/* 加入原集合对应的序号,方便生成答案 */
            intervals_right.push_back(intervals[i]);
        }
        // intervals_right 按右边界排序
        sort(intervals_right.begin(), intervals_right.end(), [&](const vector<int> &a, const vector<int> &b) {
            return a[1] < b[1]; 
        });
        // intervals 按左边界排序
        sort(intervals.begin(), intervals.end(), [&](const vector<int> &a, const vector<int> &b) {
            return a[0] < b[0];
        });
        int j = 0;
        for (int i = 0; i < intervals_size; ++i) {
            int index_right = intervals_right[i][2];
            for (; j < intervals_size; ++j) {	/* 遍历左边界数据不用重新将下标置为0 */
                int index_origin = intervals[j][2];
                if (intervals[j][0] >= intervals_right[i][1]) {
                    
                    ans[index_right] = index_origin;
                    break;
                }
            }
        }
        return ans;
    }
};
posted @ 2022-06-03 21:52  番茄元  阅读(31)  评论(0)    收藏  举报