《九日集训》第十五轮 (第五讲) 排序
知识点
排序
int cmp(const void*p1, const void *p2) { // (1)
int v1 = *(int *)p1; // (2)
int v2 = *(int *)p2; // (3)
if(v1 < v2) { // (4)
return -1;
}else if(v1 > v2) {
return 1;
}
return 0;
}
题目分析
题目1
分析
简单的快排
代码
class Solution {
public:
void quick_sort(vector<int>&q,int l,int r){
if(l>=r)return;
int i=l-1,j=r+1,x=q[(l+r)>>1];
while(i<j){
do i++;while(q[i]<x);
do j--;while(q[j]>x);
if(i<j)swap(q[i],q[j]);
}
quick_sort(q,l,j),quick_sort(q,j+1,r);
}
vector<int> sortArray(vector<int>& nums) {
int l=0,r=nums.size()-1;
quick_sort(nums,l,r);
return nums;
}
};
题目2
分析
看到次数,第一时间想到了\(unordered\_map\),但是题目要求设计时间复杂度为 \(O(n)\)、空间复杂度为$ O(1)$ 的算法解决此问题,这个想了一个多小时还是没有想到qwq,只能拿\(unordered\_map\)氵一下了( ・´ω`・ )
代码
class Solution {
public:
int majorityElement(vector<int>& nums) {
unordered_map<int,int>map;
for(auto num:nums){
map[num]++;
if(map[num]>nums.size()/2)return num;
}
return -1;
}
};
题目3
分析
看到判断次数,第一时间想到用\(map\),思路和上面一题差不多qwq
代码
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
// return set<int>(nums.begin(),nums.end()).size()!=nums.size();
unordered_map<int,int>map;
for(auto num:nums){
map[num]++;
if(map[num]>1)return true;
}
return false;
}
};
题目4
分析
看到在「线性时间」内运行并使用「线性额外空间」的算法,第一时间想到了计数排序,没想到超时了,改成了桶排序过了ヽ( ̄▽ ̄)ノ
桶排序模板如下:
vector<int> bucketSort(vector<int>& nums) {
int n = nums.size();
int maxv = *max_element(nums.begin(), nums.end());
int minv = *min_element(nums.begin(), nums.end());
int bs = 1000;
int m = (maxv - minv) / bs + 1;
vector<vector<int>>bucket(m);
for (int i = 0; i < n; ++i) {
bucket[(nums[i] - minv) / bs].push_back(nums[i]);
}
int idx = 0;
for (int i = 0; i < m; i++) {
int sz = bucket[i].size();
sort(bucket[i].begin(), bucket[i].end());
for (int j = 0; j < sz; j++)nums[idx++] = bucket[i][j];
}
return nums;
}
代码
class Solution {
public:
vector<int> bucketSort(vector<int>& nums) {
int n = nums.size();
int maxv = *max_element(nums.begin(), nums.end());
int minv = *min_element(nums.begin(), nums.end());
int bs = 1000;
int m = (maxv - minv) / bs + 1;
vector<vector<int> > bucket(m);
for (int i = 0; i < n; ++i) {
bucket[(nums[i] - minv) / bs].push_back(nums[i]);
}
int idx = 0;
for (int i = 0; i < m; ++i) {
int sz = bucket[i].size();
sort(bucket[i].begin(),bucket[i].end());
for (int j = 0; j < sz; ++j) {
nums[idx++] = bucket[i][j];
}
}
return nums;
}
int maximumGap(vector<int>& nums) {
int result=0;
vector<int>res=bucketSort(nums);
if(nums.size()==1)return 0;
for(int i=1,j=0;i<nums.size();i++,j++){
result=max(result,res[i]-res[j]);
}
return result;
}
};
题目5
分析
这题除了开一个额外数组,还可以用双指针。定义两个指针分别在数组左右两端,如果左指针执行偶数或者右指针指向奇数,指针右(左)移,如果左指针指向奇数且右指针指向偶数,那么交换一下这两个数,然后将左指针右移,右指针左移
代码
class Solution {
public:
vector<int> sortArrayByParity(vector<int>& nums) {
// vector<int>result;
// for(auto num:nums)
// if(num%2==0)result.push_back(num);
// for(auto num:nums)
// if(num%2)result.push_back(num);
int l=0,r=nums.size()-1;
while(l<r){
if(nums[l]%2==0)l++;
else if(nums[r]%2){
r--;
}else if(nums[r]%2==0 && nums[l]%2==1){
swap(nums[l],nums[r]);
l++,r--;
}
}
return nums;
}
};
题目6
分析
可以知道,时间共有$24 \times 60=1440 $种可能,当时间的数量大于\(1440\),说明有重复,返回\(0\)即可。然后对提取字符串里面的HH和MM,并转化成分钟数,即
\[S_{min}=min+hour\times60
\]
然后排序一下,求出最小差值,因为存在\(21:00-1:00\)的隔天情况,所有需要判断一下和最短隔天情况的大小,求一下最小值
代码
class Solution {
public:
int findMinDifference(vector<string>& timePoints) {
//测试用例>1440,必然有重复
if(timePoints.size()>1440)return 0;
vector<int> mins;
int res = INT_MAX;
//将字符串转成时间
for (auto time : timePoints) {
string hour(time.begin() , time.begin()+2), min(time.begin() + 3, time.end());
if (hour=="00") {
hour = "24";
}
mins.push_back(atoi(hour.c_str()) * 60 + atoi(min.c_str()));
}
sort(mins.begin(), mins.end());
for (int i = 1, j = 0; i < mins.size(); i++, j++) {
res = min(res,mins[i] - mins[j]);
}
//对可能的隔天情况像21: 00-1:00判断一下
res = min(res, 1440 + mins[0] - mins[mins.size()-1]);
return res;
}
};
题目7
分析
\[假设a_n+b_n<c_n \\ 又\because a_1<a_2<a_3<.......<a_n,b_1<b_2<b_3....<b_n
\\\therefore c_n>a_n+b_n>a_{n-1}+b_{n-1}>.....>a_1+b_1
\]
所以最大周长必定是是排序后的相邻的数组元素,依次遍历即可
代码
class Solution {
public:
int largestPerimeter(vector<int>& nums) {
sort(nums.begin(),nums.end());
for(int i=nums.size()-1;i>=2;i--){
if(nums[i]<nums[i-1]+nums[i-2])return nums[i]+nums[i-1]+nums[i-2];
}
return 0;
}
};
题目8
分析
定义一个计数器,排序后双指针,当\(最重的人+最轻的人\leq limit\),两个指针向中间移动一步,\(count++\),否则右指针左移,\(count++\)
代码
class Solution {
public:
int numRescueBoats(vector<int>& people, int limit) {
int l=0,r=people.size()-1,res=0;
sort(people.begin(),people.end());
while(l<=r){
if(people[l]+people[r]<=limit){
l++;
r--;
res++;
}else if(people[l]>limit)return -1;
else{
r--;
res++;
}
}
return res;
}
};
总结
这次杀时间最多的是c++的语法,要好好重新看一下qwq


浙公网安备 33010602011771号