Leetcode: 贪心算法


Points

  • 采用贪心策略,确保每次操作都是局部最优,从而使最后得到的结果是全局最优。ps:当局部结果互不相干,全局最优等价于局部最优的简单加和。
  • 总结:(1)排序【Leetcode 455Leetcode 435(区间大小-排序尾区间)、Leetcode 452(交区间-排序头区间)、Leetcode 406(重要性)】;(2)相邻两侧关系【Leetcode 135Leetcode 605】;(3)区间【Leetcode 435Leetcode 452】;(4)贪心定义 【Leetcode 122

Leetcode 455 Assign Cookies (Easy)

Assume you are an awesome parent and want to give your children some cookies. But, you should give each child at most one cookie.
Each child i has a greed factor g[i], which is the minimum size of a cookie that the child will be content with; and each cookie j has a size s[j]. If s[j] >= g[i], we can assign the cookie j to the child i, and the child i will be content. Your goal is to maximize the number of your content children and output the maximum number.
Example 1:
Input: g = [1,2,3], s = [1,1]
Output:1
Explanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3.
And even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content.
You need to output 1.
Example 2:
Input:g = [1,2], s = [1,2,3]
Output: 2
Explanation: You have 2 children and 3 cookies. The greed factors of 2 children are 1, 2.
You have 3 cookies and their sizes are big enough to gratify all of the children,
You need to output 2.
Constraints:
1 <= g.length <= 3 * 104
0 <= s.length <= 3 * 104
1 <= g[i], s[j] <= 231 - 1

思路:

  • 饥饿度最小的小孩最容易喂饱,所以采取的贪心策略是:每次找到饥饿度最小的小孩,用最接近它饥饿度的曲奇饼喂饱它,直到剩余的曲奇饼无法满足小孩为止。
  • “用最接近它饥饿度的曲奇饼喂饱它” <=> 对小孩饥饿度、曲奇饼大小两个序列进行升序排序,然后采用双指针的思想:如果曲奇饼大小满足了小孩,指向两个序列的指针同时后移;如果满足不了,则指向曲奇饼序列的指针后移。

代码:

class Solution {
   
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
   
        int result = 0;
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        for (int i = 0; i < s.size() && result < g.size(); i++) {
   
            if (s[i] >= g[result]) result++;
        }
        return result;
    }
};

Leetcode 135 Candy (Hard)

There are N children standing in a line. Each child is assigned a rating value.
You are giving candies to these children subjected to the following requirements:
1.Each child must have at least one candy.
2.Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?
Example 1:
Input: [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
Example 2:
Input: [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.The third child gets 1 candy because it satisfies the above two conditions.

思路:

  • 如果打算采用一次遍历,遍历过程中同时调整每个元素的两个相邻元素,使得这三个元素满足条件2,会出现混淆现象(当前的修改有可能会使得上一步的三个元素不再满足条件2),即该局部最优操作会对其它局部最优操作的结果产生干扰;如果采用两次遍历,第一次遍历解决右边元素与左边元素的大小关系,第二次遍历解决左边元素与右边元素的大小关系,这种局部最优操作不会对其它局部最优操作产生干扰。所以贪心的策略是:每次遍历只考虑并更新相邻一侧的大小关系。
  • 第一次遍历(左->右):如果右侧元素的权重大于左侧元素,则右侧元素的糖果数 = 左侧元素糖果数 + 1
  • 第二次遍历(右->左):如果左侧元素的权重大于右侧元素, 且左侧元素的糖果数小于右侧元素时,左侧元素的糖果数 = 右侧元素糖果数 + 1。

代码:

class Solution {
   
public:
    int candy(vector<int>& ratings) {
   
        if (ratings.size() <= 1) return ratings.size();
        // if (ratings.size() == 2) return ratings[0] != ratings[1] ? 3 : 2;
        vector<int> c(ratings.size(), 1);
        for (int i = 0; i < ratings.size()-1; i++) {
   
            if (ratings[i+1] > ratings[i]) c[
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值