什么是贪心算法
分配饼干例题
//贪心算法
//保证局部最优,从而使最后得到的结果是全局最优的
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1001;
int main()
{
int fin(int a[], int b[]);
int n, m;//n表示的是孩子的饥饿数,m表示的是饼干
int a[N], b[N];
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int j = 0; j < m; j++)
{
cin >> b[j];
}
sort(a, a + n);//都需要进行排序
sort(b, b + m);
printf("%d\n", find(a, b));//找到可以吃饱的孩子的数目
}
int find(int*a, int*b)
{
int a1= 0;//能吃饱孩子的数目
int b1 = 0;//饼干的下标
while (a1 < a.length() && b1 < b.length())
{
if (a[a1] <= b[b1++]) a1++;
}
return a1;
}
理解二
-
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性。
运用贪心策略在每一次转化时都取得了最优解。问题的最优子结构性质是该问题可用贪心算法求解的关键特征。贪心算法的每一次操作都对结果产生直接影响。贪心算法对每个子问题的解决方案都做出选择,不能回退。- 贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,他的选取应该满足局部优化的条件。若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加算法停止。
3.实际上,贪心算法适用的情况很少。一般对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实 际数据进行分析,就可以做出判断。
4.当发现一个问题的解决只需要考虑最优子结构的问题即可,即每一步最优,不需要考虑整体,而这时就可以用我们的贪心算法来解决问题。
例子(局部——》整体)
选择排序
分割字符串
大佬思路
class Solution {
public:
int balancedStringSplit(string s) {
int balance =0;
int count =0;
for(int i =0;i<s.size();i++){
if(s[i]=='R'){
balance ++;
}
if(s[i]=='L'){
balance--;
}
if(balance==0){
count++;
}
}
return count;
}
最优装箱
//先将各个重量的进行排序,计算数目
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1001;
int main()
{
int a[N];
int n, maxn;
cin >> n >> maxn;
for (int i = 0; i < n; i++)
{
cin >>a[i];
}
sort(a, a + n);
int num = 0, sum = 0;
for (int i = 0; i < n; i++)
{
if (sum + a[i] <= maxn)
{
num++;
sum += a[i];
}
else
break;
}
printf("%d %d", num, sum);
return 0;
}
整数配对
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1001;
int main()
{
int a[N], b[N];
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int j = 0; j < m; j++)
{
cin >> b[j];
}
sort(a, a + n);
sort(b,b + m);
int cout = 0;
int i = 0, j = 0;
while (i!=n&&j!=m)
{
if (a[i] <= a[j])
{
cout++;
i++;
j++;
}
else
{
j++;
}
}
printf("%d", cout);
return 0;
}
最大组合整数
自己写的方法一:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 10;
int main()
{
bool hash[1001] = { false };
int a[N];
for (int i = 0; i < N; i++)
{
cin >> a[i];
if (a[i])
{
hash[i] = true;
}
}
for (int j = N-1; j >= 0; j--)
{
if (hash[j])
{
while (a[j])
{
printf("%d", j);
a[j]--;
}
}
}
return 0;
}
答案(感觉有一些瑕疵,在0位置的时候怎么办呢)
//答案,写的真好,不是吗,是从后面进行遍历的
//输出的时候,用布尔变量,
// 依次的遍历整个数组,判断是否存在数,如果存在那就改变布尔变量
//输出的时候,只要判断布尔变量是否改变,(是在遍历的时候,边改变边进行输出判断)
//最后是如果都没有改变,那就只输出一个0
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 10;
int main()
{
int a[N];
for (int i = 0; i < N; i++)
{
cin >> a[i];
}
bool lfirst = false;
for (int i = N - 1; i >= 0; i--)
{
if (i > 0 && a[i] > 0)//只有在i>0时候
{
lfirst = true;
}
if (lfirst)
{
for (int j = 0; j < a[i]; j++)
{
printf("%d", i);
}
}
}
if (!lfirst)
{
printf("0");
}
return 0;
}
分配区间问题
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 10000;
struct Interval {
int l, r;
} interval[MAXN];
bool cmp(Interval a, Interval b) {
if (a.l != b.l) {
return a.l > b.l;
}
else {
return a.r < b.r;
}
}
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d%d", &interval[i].l, &interval[i].r);
}
sort(interval, interval + n, cmp);
int num = 1, lastL = interval[0].l;
for (int i = 1; i < n; i++) {
if (interval[i].r <= lastL) {
lastL = interval[i].l;
num++;
}
}
printf("%d", num);
return 0;
}
//两者的思想都是一样,先对于各个数组进行尾部的排序,然后
//进行判断是否重叠,然后进行分区间统计数目多少
买股票的最佳时机
贪心思想是:我不关心整体是高是低,我只关心下一天如果比我今天高,我就买入,如果比我今天低,我就卖出。
设 tmp 为第 i-1 日买入与第 i 日卖出赚取的利润,即 tmp = prices[i] - prices[i - 1] ;
当该天利润为正 tmp > 0,则将利润加入总利润 profit;当利润为 000 或为负,则直接跳过;
遍历完成后,返回总利润 profit。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int profit = 0;
for (int i = 1; i < prices.size(); i++) {
int tmp = prices[i] - prices[i - 1];
if (tmp > 0) profit += tmp;
}
return profit;
}
};
区间选点 问题
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 10000;
struct Interval {
int l, r;
} interval[MAXN];
bool cmp(Interval a, Interval b) {
if (a.l != b.l) {
return a.l > b.l;
} else {
return a.r < b.r;
}
}
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d%d", &interval[i].l, &interval[i].r);
}
sort(interval, interval + n, cmp);
int num = 1, lastL = interval[0].l;
for (int i = 1; i < n; i++) {
if (interval[i].r < lastL) {
lastL = interval[i].l;
num++;
}
}
printf("%d", num);
return 0;
}