贪心算法总结

贪心算法总结

贪心算法简述

贪心算法是原理最简单的一种算法,甚至可以将其中一些部分理解为常识或者是常规思维。

他采取贪心的策略,即保证每次操作都是最优的,先得到局部的最优解,从而使最终的结果是最优的。

leetcode刷题

分配问题

455.Assign Cookies(Easy)

题目描述:

有一群孩子和一堆饼干,每个孩子都有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃最多一个饼干,且只有饼干的大小大于孩子的饥饿度时,这个孩子才可以吃饱。求解最多有多少个孩子可以吃饱。

输入输出样例:

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

Output : 2


一些想法:

这里的贪心策略就是尽可能的将剩余孩子中饥饿度最小的满足,每一次只考虑最小的饥饿度。

所以算法实现就是先将所有孩子的饥饿度和饼干的大小从大到小进行排序,然后设置两个指针分别指向child和cookie,当遇到cookie的值大于等于孩子的饥饿度时,即满足条件,故将指针均后移即可。若不满足,cookie后移即可。当有一个到达尽头时,循环结束。返回已经满足的孩子数量。

代码部分:
int findContentChildren(vector<int>& children,vector<int>& cookies) {
    int child = 0 ;
    int cookie = 0 ;
    while(child<children.size() && cookie<cookies.size()){
        if(children[child] <= cookies[cookie]){
            child++ ;
            cookie++ ;
        }
        else
            cookie++ ;
    }
    return child ;
}

135.Candy(Hard)

题目描述:

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。

你需要按照以下要求,帮助老师给这些孩子分发糖果:

每个孩子至少分配到 1 个糖果。

评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。

那么这样下来,老师至少需要准备多少颗糖果呢?

输入输出样例:

Input : [1,0,2]

Output : 5



Input : [1,2,2]

Output : 4


一些想法:

一开始为了有一个基准值,方便比较,同时题目要求所有孩子都至少有一个糖果,所以先应该将所有孩子的糖果全部初始化为1.

可以分成两边进行考虑,进行两轮的遍历。如果遇到自己比邻位大的话,就在邻位的基础上加一即可。

最后将所有值相加并返回即可。

代码部分:
int candy(vector<int>& ratings){
    int size = ratings.size() ;
    if(size <= 1)
    return size ;
    vector<int> candies(,1) ;   //将所有的糖果数全部初始化为1
    //第一轮,从左往右进行比对
    for(int i = 1 ;i < size ; i++){
        if(ratings[i] > ratings[i-1]){
            candies[i] = candies[i-1]+1 ;
        }
    }
    //第二轮,从右向左进行比对
    for(int i = size-1 ; i > 0; i--){
        if(ratings[i-1] > ratings[i]){
            candies[i-1] = max(candies[i-1],ratings[i]+1) ;
        }
    }
    //最终返回所有值的和
    return accumulate(candies.begin(),candies.end(),0) ;
}


区间问题

435.Non-overlapping Intervals(Medium)

题目描述:

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

输入输出样例:
image-20210730165723809
一些想法:

选取的贪心策略是先对于所有区间的尾节点,进行升序排序,然后以保留尾节点最小而且与前一个结点无重叠区间为优先。

排序的时候会用到c++的lamda表达式,可以利用其与sort结合进行自定义排序。

代码部分:
int eraseOverlapIntervals(vector<vector<int>>& intervals){
    int sum = 0 ; //肯定要先设置一个计数器
    //进行按照尾节点的升序排序
    sort(intervals.begin(),intervals.end(),[](vector<int> a,vector<int> b){
        return a[1]>b[1] ;
    }) ;
    int pre = intervals[0][1] ;
    for(int i = 1 ; i < intervals.size() ; i++){
        if(intervals[i][0] < pre){
            sum++ ;
        }
        else{
            pre = intervals[i][1] ;
        }
    }
    return sum ;
}

605.Can Place Flowers(Easy)

题目描述:

假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

给你一个整数数组 flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种

植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false。

输入输出样例:

image-20210730171909324

image-20210730172035150

一些想法:

(本人比较拙劣的方法,本人是初级学leetcode,以后如果自己想或者发现了有更好的题解也会进一步更新的)

代码部分:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
      int m = flowerbed.size() ;
      int sum = 0 ;
      if(m == 1 && flowerbed[0] == 0){
         sum++ ;
      }
      else{
      for(int i = 0;i<m;i++){
          if(flowerbed[i] == 0){
              if(i == 0){
               if(flowerbed[i+1] == 0){
                  flowerbed[i] = 1 ;
                  sum++ ;
               }
              }
             else if(i == m-1){
                if(flowerbed[i-1] == 0){
                    flowerbed[i] = 1 ;
                    sum++ ;
                }
              }
              else {
              if(flowerbed[i-1] == 0 && flowerbed[i+1] == 0){
                 flowerbed[i] = 1 ;
                 sum++ ;
              }
              }
          }
      }
      }
      if(sum>=n)
      return true ;
      else
      return false ;
    }

未完待续......

posted @ 2021-08-04 16:42  邻菲子  阅读(248)  评论(0)    收藏  举报