【贪心算法题目练习】

1. 分发饼干

这道题目和我们之前讲到的田忌赛马的问题很相似,只不过这这里不需要劣等马去抵消掉优等马,直接上贪心策略:

先将两个数组排序。针对胃口较小的孩子,从小到大挑选饼干:

  • i. 如果当前饼干能满足,直接喂(最小的饼干都能满足,不要浪费大饼干) ;
  • ii. 如果当前饼干不能满足,放弃这个饼干,去检测下一个饼干(这个饼干连最小胃口的孩子都无法满足,更别提那些胃口大的孩子了)。

直接上代码:

cpp 复制代码
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        // 排序
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int i = 0;
        int j = 0;
        int ret = 0;
        while(j < s.size() && i < g.size())
        {
            if(s[j] >= g[i])
                ret++,j++,i++;
            else
                j++;   
        }
        return ret;
    }
};

2. 最优除法

我们可以看到这个题目的要求,它要求表达式的结果最大,那么在除数中我们可以尽量让分子大一点,让分母小一点即可,这就是我们的贪心策略:在最终的结果中,前两个数的位置是无法改变的,前两个数必定一个在分子,一个在分母,题目中说明每⼀个数的都是大于等于 2 的,所以此时可以用我们的贪心策略,为了让结果更大,我们应该尽可能的把剩下的数全都放在 「分子」上,直接上代码:

cpp 复制代码
class Solution {
public:
    string optimalDivision(vector<int>& nums) {
        int n = nums.size();
        // 先处理两个边界情况
        if(n == 1) return to_string(nums[0]);
        if(n == 2) return to_string(nums[0]) + "/" + to_string(nums[1]);
        string ret = to_string(nums[0]) + "/(" + to_string(nums[1]);
        for(int i = 2; i < n; i++)
        {
            ret += "/" + to_string(nums[i]);
        }
        ret += ")";
        return ret;
    }
};

3. 跳跃游戏Ⅱ

动态规划解法:

  • a.状态表示:dp[i] 表示从0位置开始,到达i位置时候的最小跳跃次数
  • b.状态转移方程:对于dp[i],我们遍历0~i-1区间(用指针j表示),只要能够从j位置跳到i位置(nums[j]+j>=i) ,我们就用 dp[j]+ 1更新dp[i]里面的值,找到所有情况下的最小值即可。

类似层序遍历的过程:

  • 用类似层序遍历的过程,将第i次跳跃的「起始位置」和「结束位置」找出来,用这次跳跃的情况,更新出下一次跳跃的「起始位置」和「终止位置」这样「循环往复」,就能更新出到达n一1位置的最小跳跃步数

直接上代码:

cpp 复制代码
class Solution {
public:
    int jump(vector<int>& nums) {
        int left = 0;
        int right = 0;
        int ret = 0;
        int maxpos = 0;
        while(true)
        {
            // 判断是否已经跳到最后一个位置
            if(nums.size() - 1 <= maxpos)
                return ret;
            // 遍历当层节点的最大步数
            for(int i = left; i <= right; i++)
            {
                maxpos = max(maxpos, nums[i] + i);
            }
            // 更新下一层的区间
            left = right + 1;
            right = maxpos;
            ret++;
        }
    }
};

4. 跳跃游戏

这个题目和上面的题目思路基本上差不多,但是上一个题目的明显说了一定会到达最后一个下标位置,而我们这道题目是判断能否到达最后一个下标位置,基于上一个题目我们仅需修改⼀下返回值即可,直接上代码啦!!!

cpp 复制代码
class Solution {
public:
    bool canJump(vector<int>& nums) {
        int left = 0;
        int right = 0;
        int maxpos = 0;
        int n = nums.size();
        while(left <= right)// 以防跳不到 n - 1 的位置
        {
            // 判断是否已经能跳到最后⼀个位置
            if(maxpos >= n - 1)
                return true; 
            for(int i = left; i <= right; i++)
            {
                maxpos = max(maxpos, nums[i] + i);
            }
            left = right + 1;
            right = maxpos;
        }
        return false;
    }
};

5. 加油站

暴力解法:

  • a. 依次枚举所有的起点;
  • b. 从起点开始,模拟⼀遍加油的流程
  • c. 如果油的剩余量小于0,代表无论怎样,你都不可能绕环路行驶一周,否则可以。
cpp 复制代码
class Solution
{
public:
	int canCompleteCircuit(vector<int>& gas, vector<int>& cost)
	{
		int n = gas.size();
		for (int i = 0; i < n; i++) // 依次枚举所有的起点
		{
            int rest = 0; // 标记⼀下净收益
            for (int step = 0; step < n; step++) // 枚举向后⾛的步数
            {
                int index = (i + step) % n; // 求出⾛step步之后的下标

                rest = rest + gas[index] - cost[index];
                if (rest < 0) break;
            }
            if (rest >= 0) return i;
		}
		return -1;
	}
};

但是此时会超出时间限制,复杂度太高,我们可以优化一下哈,我们发现,当从 i 位置出发,走了 step 步之后,如果失败了。那么 [i, i + step] 这个区间内任意⼀个位置作为起点,都不可能环绕⼀圈。

因此我们枚举的下⼀个起点,应该是 i + step + 1。

cpp 复制代码
class Solution
{
public:
	int canCompleteCircuit(vector<int>& gas, vector<int>& cost)
	{
		int n = gas.size();
		for (int i = 0; i < n; i++) // 依次枚举所有的起点
		{
            int rest = 0; // 标记⼀下净收益
            int step = 0;
            for (; step < n; step++) // 枚举向后⾛的步数
            {
                int index = (i + step) % n; // 求出⾛step步之后的下标

                rest = rest + gas[index] - cost[index];
                if (rest < 0) break;
            }
            if (rest >= 0) return i;
            i = i + step; // 优化
		}
		return -1;
	}
};
相关推荐
聚客AI13 小时前
🙋‍♀️Transformer训练与推理全流程:从输入处理到输出生成
人工智能·算法·llm
大怪v15 小时前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
惯导马工17 小时前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
骑自行车的码农18 小时前
【React用到的一些算法】游标和栈
算法·react.js
博笙困了19 小时前
AcWing学习——双指针算法
c++·算法
moonlifesudo19 小时前
322:零钱兑换(三种方法)
算法
NAGNIP2 天前
大模型框架性能优化策略:延迟、吞吐量与成本权衡
算法
美团技术团队2 天前
LongCat-Flash:如何使用 SGLang 部署美团 Agentic 模型
人工智能·算法
Fanxt_Ja2 天前
【LeetCode】算法详解#15 ---环形链表II
数据结构·算法·leetcode·链表
侃侃_天下2 天前
最终的信号类
开发语言·c++·算法