leedcode题解-贪心

本文解析了包括分配饼干、无重叠区间、投飞镖刺破气球等在内的八个经典算法问题,通过示例输入输出及代码实现展示了每道题目的解决思路与方法。

1、分配饼干

455. Assign Cookies (Easy)

题目描述:每个孩子都有一个满足度,每个饼干都有一个大小,只有饼干的大小大于等于一个孩子的满足度,该孩子才会获得满足。求解最多可以获得满足的孩子数量。

Input: [1,2], [1,2,3] Output: 2

思路:对饼干大小、孩子的满足度排序,尽最大可能满足更多的孩子;

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

2、无重叠区间

题目描述:计算让一组区间不重叠所需要移除的区间个数。Input: [ [1,2], [1,2], [1,2] ] Output: 2

Input: [ [1,2], [2,3] ] Output: 0

因为每次选取的区间的end很重要,它将决定后面的不重叠区间数,若end尽量小,则留给后面的可能区间更大。计算最多的不重叠区间数,再用总区间数减去不重叠区间数,既可得需要移除的区间数。因此按照区间的end进行排序,若当前区间的start<上一个区间的end,则舍弃这个区间。否则count++;

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class Solution {
public:
    static bool cmp(const Interval &x,const Interval &y){
        return x.end<y.end;
    }
    int eraseOverlapIntervals(vector<Interval>& intervals) {
        if(intervals.empty())
            return 0;
        sort(intervals.begin(),intervals.end(),cmp);
        int curend=intervals[0].end;
        int count=1;
        for(int i=1;i<intervals.size();++i){
            if(intervals[i].start<curend)
                continue;
            else{
                count++;
                curend=intervals[i].end;
            }
        }
        return intervals.size()-count;
    }
};

3、投飞镖刺破气球

452. Minimum Number of Arrows to Burst Balloons (Medium)

与2一样,也是找不重叠区间;

class Solution {
public:
    static bool cmp(const pair<int,int>&x,const pair<int,int>&y){
        return x.second<y.second;
       
    }
    int findMinArrowShots(vector<pair<int, int>>& points) {
        if(points.empty())
            return 0;
        sort(points.begin(),points.end(),cmp);
        int curend=points[0].second;
        int count=1;
        for(int i=1;i<points.size();++i){
            if(points[i].first>curend)//当后一个区间的start>前一个区间的end(这里等于是算入重叠区域的)则箭的数量+1,当前的end门槛值相应变化
            { count++;
              curend=points[i].second;  
            }
            else{
                continue;//用了一支箭后就要一直往后判断后面的区间是否与当前区间重叠,尽量使用少数量的箭,若出现一个不符合的区间,就要重新使用另一只箭
            }
        }
        return count;
    }
};

4、根据身高和序号重组队列

406. Queue Reconstruction by Height(Medium)

由于题目给的推理信息是:k是排在这个人前面且身高大于或等于h的人数
所以当要判断某一个人的位置时,我们一定要知道所有比他高的人的信息,即让高的人先出现。
当我们知道所有比他高的人的信息,就可以很简单的判断他的位置了,因为他就是在队列中第k+1个人。
(1)首先按h从高到低排序,h相同的按k从小到大排序
(2)进行排序后,当对第i个人进行位置判断时,他告诉我们“前面比他高或与他等高的人的个数为k”,并且前面已经进行排序的人都比他高或者与他等高,所以可以判断在前i个人中,他的排序位置为k+1。

class Solution {
public:
    static bool cmp(pair<int,int>&x,const pair<int,int>&y){
        if(x.first!=y.first)
            return x.first>y.first;
        else
            return x.second<y.second;
    }
    vector<pair<int, int>> reconstructQueue(vector<pair<int, int>>& people) {
        vector<pair<int,int>>res;
        if(people.empty())
            return res;
        sort(people.begin(),people.end(),cmp);
        vector<pair<int,int>>::iterator iter;
        iter=people.begin();
        for(int i=0;i<people.size();++i){
            pair<int,int> tmp=people[i];
            iter=people.begin()+i;
            people.erase(iter);
            people.insert(people.begin()+tmp.second,tmp);
        }
        return people;
    }
};

5、分隔字符串使同种字符出现在一起

763. Partition Labels (Medium)

class Solution {
public:
    vector<int> partitionLabels(string S) {
        vector<int> res;
        if(S.size()<=0)
            return res;
        for(int i=0;i<S.size();){
             int start=i;
            int end=S.find_last_of(S[i]);
            if(end==string::npos)//若没有找到,返回-1;
                end=start;
             //循环判断第一个字母的start与end之间每个字母的end,找到最大的end
            for(int j=start+1;j<end;++j){
                if(S.find_last_of(S[j])>end)
                {
                    end=S.find_last_of(S[j]);
                }
            }
            res.push_back(end-start+1);
            i=end+1;
        }
        return res;
    }
};

6、种植花朵

605. Can Place Flowers (Easy)

class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        if(flowerbed.empty())
            return false;
        int count=0;
        int len=flowerbed.size();
        for(int i=0;i<len;i++){
            if(flowerbed[i]==1)//若当前已种植了花朵,则跳过
                continue;
            else{
                int pre=i==0?0:flowerbed[i-1];
    //判断当前的花坛是否为第一个与最后一个,若为第一个,则设置pre为0;若为最后一个,则设置next为0;
                int next=i==len-1?0:flowerbed[i+1];
                if(pre==0&&next==0){
  //pre与next同时为0,可种植花朵,并把这个花坛的值设置为1,以影响后面的种植策略
                    count++;
                    flowerbed[i]=1;
                }
            }
        }
        if(count>=n)
            return true;
        else
            return false;
    }
};

7、判断是否为子序列

392. Is Subsequence (Medium)

class Solution {
public:
    bool isSubsequence(string s, string t) {
        if(s.length()==0)
            return true;
        int i=0;int j=0;
        while(i<s.length()&&j<t.length()){
            if(s[i]==t[j]){
                i++;
                j++;
            }
            else
                j++;
        }
        if(i==s.length())
            return true;
        else
            return false;
    }
};




class Solution {
public:
    bool isSubsequence(string s, string t) {
        if(s.length()==0)
            return true;
         string::size_type curplace;
        if(t.find(s[0])!=string::npos)
             curplace=t.find(s[0]);
        else
            return false;
        for(int i=1;i<s.length();++i){
            if(t.find(s[i],curplace+1)!=string::npos)//从上一次找到前一个字符的位置开始找
               curplace=t.find(s[i],curplace+1);
            else
                return false;
        }
           return true;
    }
};

 

8、修改一个数成为非递减数组

665. Non-decreasing Array (Easy)

class Solution {
public:
    bool checkPossibility(vector<int>& nums) {
        if(nums.empty())
            return false;
        int changeflag=1;
        for(int i=1;i<nums.size();++i){
            if(nums[i-1]<=nums[i])
                continue;
            if(changeflag!=0)
              changeflag--;
            else 
                return false;
             if(i-2>=0&&nums[i-2]>nums[i])
                 nums[i]=nums[i-1];
             else
                 nums[i-1]=nums[i];
        }
        
        return true;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值