寒假刷题打卡第三天 | 排序 & 贪心

  1. 荷兰国旗问题
    这个问题很简单,遍历一遍整个数组,统计一下没个数字的个数,搞定。
//include <algorithm>// swap需要
class Solution {
public:
    void sortColors(vector<int>& nums) {
        vector<int> v(3,0);
        for(int &x:nums)
            v[x]++;
        int i=0;
        for(int j=0;j<3;j++)
        {
            while(v[j]--)
                nums[i++]=j;
        }
    }
};

下面是贪心算法部分

  1. 分发小饼干
    我手写了排序,发现超时,嘤嘤嘤。。。
class Solution {
public:
    void quicksort(vector<int> & v, int i, int j)
    {
        if(i>=j)
        return;
        int oj=j;//此处bug找了一个小时!!
        int flag = v[i];
        while(i<j)
        {
            while(v[j]>=flag && i<j)
                j--;
            if(i<j)
                v[i++]=v[j];
            while(v[i]<=flag && i<j)
                i++;
            if(i<j)
                v[j--]=v[i];
        }
        v[i]=flag;
        quicksort(v, 0, i-1);
        quicksort(v, i+1, oj);  //不要写成j!!!
    }
    int findContentChildren(vector<int>& g, vector<int>& s) {
        quicksort(g, 0, g.size()-1);
        for(int &x:g)
            cout<<x<<endl;
        quicksort(s, 0, s.size()-1);
        int i=0,j=0,ans=0;
        while(i<g.size())
        {
            while(j<s.size() && s[j]<g[i])  //一定不要写反!!!(s[j]<g[i]&&j<s.size() )
            {
                j++;
            }
            if(j<s.size())
            {
                i++;
                ans++;
                j++;
            }
            
            else
                break;
        }
        return ans;

    }
};

事实证明,还是调库最香

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        int i=0,j=0,ans=0;
        while(i<g.size())
        {
            while(j<s.size() && s[j]<g[i])
            {
                j++;
            }
            if(j<s.size())
            {
                i++;
                ans++;
                j++;
            }
            
            else
                break;
        }
        return ans;

    }
};
  1. 不重叠的区间个数
    看了答案:
class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if (intervals.empty()) {
            return 0;
        }
        
        sort(intervals.begin(), intervals.end(), [](const auto& u, const auto& v) {
            return u[1] < v[1];   
        });

        int n = intervals.size();
        int right = intervals[0][1]; //考虑如果元素个数为0怎么办
        int ans = 1;
        for (int i = 1; i < n; ++i) {
            if (intervals[i][0] >= right) {
                ++ans;
                right = intervals[i][1];
            }
        }
        return n - ans;
    }
};

贪心思想所谓的局部最优构成全局最优,体现在这个问题上实际就是先确定第一个元素,再去确定下一个元素。但是如何去确定第一个元素,通常需要用到排序,取最值,也就是局部最优。
4. 投飞镖刺破气球

class Solution {
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if(points.empty())
            return 0;
        sort(points.begin(),points.end(),[](const auto& u, const auto& v) {
            return (u[0] < v[0]) && (u[1] < v[1]);   
            //首先想到的是根据左端点值排序,没有考虑到左端点相同时还应该以右端点排序
            //貌似上面这种写法并不能实现我想要的功能,return u[0] < v[0] || (u[0] == v[0] && u[1] > v[1]);
            //看了一下答案,答案是直接对右端点进行排序??为何??
        });
        int right=points[0][1];
        int ans=1;
        for(int i=1;i<points.size();i++)
        {
            if(points[i][0]>right)
            {
                ans++;
                right=points[i][1];
            }
        }
        return ans;
    }
};
  1. 根据身高重建队列
    核心思想:根据身高排序,并将第i个元素放到第i+1个空格处。如果身高相等,按照k值做第二次排序。
class Solution {
public:
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(), [](const vector<int>& u, const vector<int>& v) {
            return u[0] < v[0] || (u[0] == v[0] && u[1] > v[1]);
        });
        int n = people.size();
        vector<vector<int>> ans(n);
        for (const vector<int>& person: people) {
            int spaces = person[1] + 1;
            for (int i = 0; i < n; ++i) {
                if (ans[i].empty()) {
                    --spaces;
                    if (!spaces) {
                        ans[i] = person;
                        break;
                    }
                }
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值