贪心算法1

179 阅读2分钟

小知识,大挑战!本文正在参与“   程序员必备小知识   ”创作活动

本文同时参与 「掘力星计划」   ,赢取创作大礼包,挑战创作激励金

先花点时间把之前刷的几十题整理,然后按照章节继续多做点加深理解。

贪心算法

贪心算法或贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到的结果是全局最优的

1、分发饼干

问题:给定所有的饼干大小和孩子的胃口值,目的是满足条件下的最大分配。

算法:挺好想的,要让饼干物尽其用,每个饼干分配给恰好满足的孩子,或者说每个孩子分到的饼干刚好够自己用的。采用贪心的方法去满足孩子。先对数组排序,然后2个下标贪心的每次恰好满足孩子的胃口。

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

            }
            return weikou;


    }
};

2.分发糖果(困难)

题目:

算法: 贪心的解决这个问题。 因为每个得分高的孩子得到的糖果更多。可以先顺序的遍历一遍,假如孩子比左侧的孩子的得分高,那么它的糖果更多。然后从右往左的遍历一遍,让一个孩子和右边对比i,得分比右侧的孩子高,就比右侧孩子的糖果更多。每次只考虑相邻一侧的值的大小。 先左侧的满足,后右侧的满足,右侧满足的过程中要保证左侧的结果,也就是糖果取最大值。

class Solution {
public:
    int candy(vector<int>& ratings) {
            int +n =ratings.size();
            vector<int>result(n,1);
            for(int i=1;i<n;i++)
            {

                if(ratings[i]>ratings[i-1])
                    result[i]=result[i-1]+1;
            }

            for(int i=n-2;i>=0;i--)
            {

                    if( ratings[i]>ratings[i+1])
                       result[i]=max(result[i],result[i+1]+1);

            }
            return accumulate(result.begin(),result.end(),0);
    }
};

3.无重叠区间

问题:

解法:贪心的去保留区间,每次保留下来的区间末尾值最小。因此可以按照末尾值对区间排序,不断的删除。最后计算的是保留的区间, 这里的贪心的地方在于:每次让余下的空间最大,那么每次保留的是末尾值最小的区间。保证当前区间满足的情况,去更新下一次的末尾区间。如果有重叠,删除数量+1.

class Solution {
  static bool compare(const vector<int> &a, const vector<int> &b) {
return a[1] < b[1];
};
public:

    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
            if(intervals.empty()) return 0;
            sort(intervals.begin(),intervals.end(),compare);
            int pre=-1;
            int count=0;
            pre =intervals[0][1];
            for(int i=1;i<intervals.size();i++)
            {
                if(pre>intervals[i][0])
                    {

                        count++;
                    }
                    else{
                         pre =intervals[i][1];
                    }

            }
            return count;
    }
};

4.种花问题

问题:

解法:计算最多可以种多少朵花!!花坛是一维的,题目给了种花的条件。因此只用从左开始遍历一遍,每经过一个位置判断条件去种花,贪心的从左往右种。每次种花都是局部最优解。

class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        int count=0;

        if(flowerbed.size()==1)
            {
                if(flowerbed[0]==0)
                    count++;
                return count>=n;
            }

        for(int i=0;i<flowerbed.size();i++)
        {
            if(flowerbed[i]==0)
            {
            if(i==0)
                {
                if(flowerbed[1]==0)
                    {
                        flowerbed[0]=1;
                        count++;
                    }
                }
            else if( i==flowerbed.size()-1)
               {
                if(flowerbed[flowerbed.size()-2]==0)
                    {
                        flowerbed[flowerbed.size()-1]=1;
                        count++;
                    }
                }else{
             if(flowerbed[i-1]==0 && flowerbed[i+1]==0)
                    {
                        flowerbed[i]=1;
                        count++;
                    }
                }
            }
        }
        return count>=n;
    }
};