01、贪心算法

1.1、分配问题(Assign Cookies)leetcode455

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

        输入输出样例:

        输入两个数组,分别代表孩子的饥饿度和饼干的大小。输出最多有多少个孩子可以吃饱的数量。

        input:[1,2],[1,2,3]

        output:2

        解题思路:

        因为饥饿度最小的孩子最容易吃饱,所以我们先考虑这个孩子。为了尽量使得剩下的饼干可以满足饥饿度更大的孩子,所以我们应该把大于等于这个孩子饥饿度的,且大小最小的饼干给这个孩子。满足这个孩子之后,我们采取同样的策略,考虑剩下孩子里饥饿度最小的孩子,直到满足所有条件的饼干存在。

        简而言之,这里贪心的策略是,给剩余孩子里最小饥饿度的孩子分配最小的能饱腹的饼干。

        至于具体的实现,因为我们需要获取大小关系,一个便捷的方法就是把孩子和饼干分别排序。这样我们就可以从饥饿度最小的孩子和大小最小的饼干出发,计算有多少个对子可以满足条件。

#include
#include
#include
using namespace std;

int FindContentChildren(vector &children_vec, 
						vector &cookies_vec) {
  sort(children_vec.begin(), children_vec.end());
  sort(cookies_vec.begin(), cookies_vec.end());
  int children = 0, cookies = 0;
  while (children < children_vec.size() && cookies < cookies_vec.size()) {
	if (children_vec[children] <= cookies_vec[cookies]) {
	  children++;
	   cookies++;
	}
	else {
	  cookies++;
	}
  }
  return children;
}

void main() {
  vector children_vec = { 1,2 };
  vector cookies_vec = { 1,2,3 };
  cout << "the number can content children is : " <<
	FindContentChildren(children_vec, cookies_vec) << endl;
  cout << "hello woeld" << endl;
}

1.2 、Candy LeetCode135

        题目描述:

        一群孩子站成一排,每个孩子都有自己的评分,现在需要给这些孩子分糖果,规则是如果一个孩子的评分比自己身旁的一个孩子要高,那么这个孩子就必须得到比身旁孩子更多的糖果;所有孩子至少有一个糖果。求解最少需要多少个糖果。

        输入输出样例:

        输入是一个数组,表示孩子的评分。输出是最少的糖果数量。

        input:[1,0,2]

        output: 5

        在这个样例中,最少的糖果分法是[2,1,2].

        题解:

        把所有孩子的糖果初始化为1;先从左往右遍历一遍,如果右边孩子的评分比左边孩子高,则右边孩子的糖果数更新为左边孩子的糖果数加1;再从右往左遍历,如果左边的孩子评分比右边孩子高,且左边孩子的糖果数不大于右边孩子的糖果数时,左边孩子的糖果数更新为右边孩子糖果数加1。通过两次遍历,就可以实现目标。

        再样例中,我们初始化糖果分配为[1,1,1],第一次遍历结果为[1,1,2],第二次遍历结果为[2,1,2].

#include
#include
#include
#include
using namespace std;

int Candy(vector& hildren_score) {
  int size = hildren_score.size();
  if (size < 2) {
	return size;
  }
  vector num(size, 1);
  for (int i = 0; i < size-1; i++) {
	if (hildren_score[i] < hildren_score[i + 1]) {
	  num[i + 1] = num[i] + 1;
	}
  }
  for (int j = size - 1; j > 0; j--) {
	if (hildren_score[j - 1] > hildren_score[j]) {
	  num[j - 1] = max(num[j - 1], num[j] + 1);
	}
  }
  return accumulate(num.begin(), num.end(),0);
}

void main() {
  vector children_score = { 1,0,2 };
  cout << "the total candy number is : " <<
	Candy(children_score) << endl;
  cout << "hello world" << endl;
}

1.3、 Non Overlapping Intervals leetcoe 435

题目描述:

        给定多个区间,计算让这些区间互不重叠所需要移除区间的最小个数。起止相连不算重叠。

输入样例:

        input:[[1,2],[2,4],[1,3]]

        output:1

        在这个题解中,我们可以移除[1,3],使得剩下的区间不重叠。

题解:

        在选择需要保留的区间时,区间的结尾十分重要:选择的区间结尾越小,余留给其他区间的空间越大,就越能保留更多的区间。我们这里使用C++的lambda,结合sort()函数进行自定义排序。

        在样例中,排序后的数组为[[1,2],[1,3],[2,4]].按照我们的贪心策略,首先初始化区间[1,2];由于[1,3]与[1,2]想交,我们跳过该区间;由于[2,4]与[1,2]不相交,我们将其保留。

#include
#include
#include
using namespace std;

int EraseOverlapIntervals(vector> intervals_vec) {
  sort(intervals_vec.begin(), intervals_vec.end(),
	   [](vectora, vectorb) {
	     return a[1] < b[1];
	   });
  int pre_value = intervals_vec[0][1];
  int erasr_num = 0;
  for (int i = 1; i < intervals_vec.size(); i++) {
	if (intervals_vec[i][0] < pre_value) {
	  erasr_num++;
	}
	else {
	  pre_value = intervals_vec[i][1];
	}
  }
  return erasr_num;
}

void main() {
  vector> intervals_vec = { {1,2},{2,4},{1,3} };
  cout << "the number will be rease is : " << EraseOverlapIntervals(intervals_vec) 
    << endl;
  cout << "hello world" << endl;
}

你可能感兴趣的:(贪心算法,算法)