《九日集训》第十五轮 (第五讲) 排序

知识点

排序

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

912. 排序数组

分析

简单的快排

代码

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

169. 多数元素

分析

看到次数,第一时间想到了\(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

217. 存在重复元素

分析

看到判断次数,第一时间想到用\(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

164. 最大间距

分析

看到在「线性时间」内运行并使用「线性额外空间」的算法,第一时间想到了计数排序,没想到超时了,改成了桶排序过了ヽ( ̄▽ ̄)ノ

桶排序模板如下:

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

905. 按奇偶排序数组

分析

这题除了开一个额外数组,还可以用双指针。定义两个指针分别在数组左右两端,如果左指针执行偶数或者右指针指向奇数,指针右(左)移,如果左指针指向奇数且右指针指向偶数,那么交换一下这两个数,然后将左指针右移,右指针左移

代码

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

539. 最小时间差

分析

可以知道,时间共有$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

976. 三角形的最大周长

分析

\[假设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

881. 救生艇

分析

定义一个计数器,排序后双指针,当\(最重的人+最轻的人\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
image

posted @ 2022-04-01 22:35  灰之魔女伊蕾娜  阅读(40)  评论(0)    收藏  举报