前言
欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
今天是五月集训第三天:排序
一、练习题目
1464. 数组中两元素的最大乘积
1636. 按照频率将数组升序排序
1287. 有序数组中出现次数超过25%的元素
436. 寻找右区间
二、算法思路
- 1、1464. 数组中两元素的最大乘积:掉包侠排序,找最大数和次大数。
- 2、1636. 按照频率将数组升序排序:自定义排序。
- 3、1287. 有序数组中出现次数超过25%的元素:按升序排好序后,相邻的就是相同的,统计次数,用cnt*4来解决小数的问题。
- 4、436. 寻找右区间:需要维护两个区间,一个按照左端点排序,一个是右端点的排序。
三、源码剖析
// 1464. 数组中两元素的最大乘积
class Solution {
public:
int maxProduct(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
return (nums[n - 1] - 1) * (nums[n - 2] - 1);
}
};
- 1、排序。
// 1636. 按照频率将数组升序排序
class Solution {
public:
vector<int> frequencySort(vector<int>& nums) {
unordered_map<int, int> cnt;
for(auto& num : nums) {
cnt[num]++;
}
sort(nums.begin(), nums.end(), [&](int a, int b){
return cnt[a] != cnt[b] ? cnt[a] < cnt[b] : a > b;
});
return nums;
}
};
- 1、调用API。
// 1287. 有序数组中出现次数超过25%的元素
class Solution {
public:
int findSpecialInteger(vector<int>& arr) {
int n = arr.size();
sort(arr.begin(), arr.end());
int cnt = 1;
for (int i = 1; i < n; ++i) {
if(arr[i] == arr[i - 1]) {
cnt++;
if(cnt * 4 > n) {
return arr[i];
}
}else {
cnt = 1;
}
}
return cnt;
}
};
- 1、排序后统计。
// 436. 寻找右区间
class Solution {
public:
vector<int> findRightInterval(vector<vector<int>>& intervals) {
vector<int> ret;
int j = 0;
vector<vector<int>> intervalsCopy;
for(int i = 0; i < intervals.size(); ++i) {
intervalsCopy.push_back(intervals[i]);
intervalsCopy.back().push_back(i);
}
for(int i = 0; i < intervals.size(); ++i) {
intervals[i].push_back(i);
ret.push_back(-1);
}
sort(intervals.begin(), intervals.end(), [&](const vector<int>& a, const vector<int>& b){
return a[1] < b[1];
});
sort(intervalsCopy.begin(), intervalsCopy.end(), [&](const vector<int>& a, const vector<int>& b){
return a[0] < b[0];
});
for(int i = 0; i < intervals.size(); ++i) {
int preidx = intervals[i][2];
for(; j < intervalsCopy.size(); ++j) {
int prejdx = intervalsCopy[j][2];
if(intervalsCopy[j][0] >= intervals[i][1]) {
ret[preidx] = prejdx;
break;
}
}
}
return ret;
}
};
- 1、排序后加贪心的思想。