数据结构刷题之贪心算法

贪心算法(Greedy Algorithm)

是一种在每个步骤中都选择当前最优解的算法设计策略。它通常用于解决优化问题,例如最小化成本或最大化收益。贪心算法的核心思想是:在每一步选择中,都做出局部最优的选择,希望最终能得到全局最优解。

贪心算法的特点

贪心选择性质:

一个问题的整体最优解可以通过一系列局部最优选择来构造。

每次选择只依赖于当前状态,而不考虑未来的影响。

最优子结构性质:

一个问题的最优解包含其子问题的最优解。

简单高效:

贪心算法通常比动态规划等方法更简单、更高效,但适用范围有限。

经典题目

1.找零问题

给定不同面额的硬币和一个总金额,要求使用最少数量的硬币凑出该金额。

分析一下这个问题:这种问题肯定是先使用大的去找,大的找不完采用晓得,典型的局部最优解-->整体最优解

思路先用大的找->再用小的找

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int minCoins(vector<int>& coins, int amount) {
    // 对硬币面额从大到小排序
    sort(coins.begin(), coins.end(), greater<int>());
    
    int count = 0; // 记录硬币数量
    for (int coin : coins) {
        if (amount == 0) break; // 如果金额为 0,结束循环
        count += amount / coin; // 使用当前面额的硬币尽可能多
        amount %= coin;         // 更新剩余金额
    }
    
    return amount == 0 ? count : -1; // 如果无法找零,返回 -1
}

int main() {
    vector<int> coins = {1, 5, 10, 25}; // 硬币面额
    int amount;
    cout << "请输入总金额: ";
    cin >> amount;

    int result = minCoins(coins, amount);
    if (result != -1) {
        cout << "最少需要 " << result << " 枚硬币。" << endl;
    } else {
        cout << "无法找零。" << endl;
    }

    return 0;
}```
2. 活动选择问题
给定一组活动及其开始时间和结束时间,求最多能参加多少个不重叠的活动。
对于活动选择问题,贪心策略通常是优先选择结束时间最早的活动。原因如下:
如果一个活动的结束时间较早,那么它留下的时间窗口就更大,从而为后续活动提供了更多可能的选择。
这种策略确保每次选择都尽可能地为后续活动腾出空间,从而最大化可参加的活动数量。
```cpp
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct Activity {
    int start, end;
};

// 按照活动结束时间排序
bool compare(Activity a, Activity b) {
    return a.end < b.end;
}

int maxActivities(vector<Activity>& activities) {
    // 按结束时间排序
    sort(activities.begin(), activities.end(), compare);

    int count = 1; // 至少可以选择第一个活动
    int lastEnd = activities[0].end;

    for (int i = 1; i < activities.size(); ++i) {
        if (activities[i].start >= lastEnd) { // 如果当前活动与上一个活动不冲突
            count++;
            lastEnd = activities[i].end; // 更新最后一个活动的结束时间
        }
    }

    return count;
}

int main() {
    vector<Activity> activities = {{1, 3}, {2, 5}, {4, 7}, {6, 9}};
    cout << "最多可以参加 " << maxActivities(activities) << " 个活动。" << endl;
    return 0;
}
  1. 分糖果问题
    有若干孩子和糖果,每个孩子有一个贪婪因子(表示至少需要多少糖果才能满足),每个糖果有一个大小。问最多能满足多少孩子?
    策略:
    优先满足需求最小的孩子:因为需求小的孩子更容易被满足,这样可以腾出更多较大的糖果来满足其他孩子。
    优先使用最小的糖果:因为较小的糖果可能无法满足需求大的孩子,但可以满足需求小的孩子。
cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int findContentChildren(vector<int>& g, vector<int>& s) {
    // 对孩子的贪婪因子和糖果大小进行排序
    sort(g.begin(), g.end());
    sort(s.begin(), s.end());

    int child = 0, cookie = 0;
    while (child < g.size() && cookie < s.size()) {
        if (s[cookie] >= g[child]) { // 如果当前糖果可以满足孩子
            child++; // 满足的孩子数加 1
        }
        cookie++; // 移动到下一个糖果
    }

    return child; // 返回满足的孩子数
}

int main() {
    vector<int> g = {1, 2, 3}; // 孩子的贪婪因子
    vector<int> s = {1, 1};    // 糖果的大小

    cout << "最多可以满足 " << findContentChildren(g, s) << " 个孩子。" << endl;
    return 0;
}
  1. 最优装载问题
    有一艘船,载重量为 W,有若干货物,每个货物有重量 wi。求最多能装多少货物。
cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int maxLoad(vector<int>& weights, int W) {
    // 按货物重量从小到大排序
    sort(weights.begin(), weights.end());

    int count = 0; // 记录装入的货物数量
    for (int weight : weights) {
        if (W >= weight) { // 如果还能装下当前货物
            count++;
            W -= weight; // 更新剩余载重量
        } else {
            break;
        }
    }

    return count;
}

int main() {
    vector<int> weights = {4, 8, 1, 5, 2}; // 货物重量
    int W;
    cout << "请输入船的最大载重量: ";
    cin >> W;

    cout << "最多可以装载 " << maxLoad(weights, W) << " 件货物。" << endl;
    return 0;
}
相关推荐
ting94520007 小时前
Humalike X Hermes 深度技术剖析:单指令注入群聊社交智能的底层架构、算法与跨 IM 平台实现
人工智能·算法·架构
吴声子夜歌7 小时前
Java面试——算法
java·算法·面试
h_a_o777oah7 小时前
【图论】Tarjan 缩点:解决有向图中环的问题
c++·算法·图论·acm·强连通分量·缩点·tarjan
Tisfy7 小时前
LeetCode 1386.安排电影院座位:哈希表+位运算
算法·leetcode·散列表·题解·哈希表
Nil2088 小时前
leetcode 199二叉树的右视图
算法·leetcode·深度优先
M78佐菲9 小时前
c语言学习笔记:排序与查找方法整理
linux·c语言·笔记·学习·算法
AI备案指南-满满11 小时前
人工智能拟人化互动服务安全自评估报告的评估要点有哪些?
人工智能·算法·安全·机器人·大模型备案·算法备案
LuminousCPP11 小时前
数据结构‑二叉树(二):二叉堆从零实现|Heap结构设计 + 建堆优化 + 堆排序深度解析
c语言·数据结构·笔记·二叉树
土司大王13 小时前
LeetCode hot100——两两交换链表中的节点
算法·leetcode·职场和发展