贪心法

作者: 徐凯_xp | 来源:发表于2018-03-12 11:17 被阅读4次
Eg.贪心法,钞票支付问题

有1元、5元、10元、20元、100元、200元的钞票无穷多张。现使用这些钞 票支付X元,最少需要多少张?
例如,X = 628

最佳支付方法: 3张200块的,1张20块的,1张5块的,3张1块的; 共需要3+1+1+3=8张。

直觉告诉我们:尽可能多的使用面值较大的钞票!
贪心法: 遵循某种规律,不断贪心的选取当前最优策略的算法设计方法。
分析:面额为1元、5元、10元、20元、100元、200元,任意面额是比自己小的面额的倍数关系。 所以当使用一张较大面额钞票时,若用较小面额钞票替换,一定需要更多的其他面额的钞票!

#include<stdio.h>
int main(){
    const int RMB[]= {200,100,20,10,5,1};
    const int NUM = 6;//6种面值
    int X = 628;
    int count = 0;
    for(int i= 0;i< NUM;i++){
        int use = X / RMB[i];需要面额为RMB[i]的use张
        count + = use;
        X = X -RMB[i] * use;
        printf("需要面额为%d 的%d张",RMB[i],use);
        printf("剩余需要支付金额%d.\n",X);
    }
    printf("总共需要%d张\n",count);
    return 0;
}

LeetCode 455. Assign Cookies

分糖果

已知一些孩子和一些糖果,每个孩子有需求因子g,每个糖果有大小s,当 某个糖果的大小s >= 某个孩子的需求因子g时,代表该糖果可以满足该孩子;求使用这 些糖果,最多能满足多少孩子?(注意,某个孩子最多只能用1个糖果满足)

例如,需求因子数组g = [5, 10, 2, 9, 15, 9];糖果大小数组s = [6, 1, 20, 3, 8];最多可以 满足3个孩子。

贪心规律

需求因子数组 g = [2, 5, 9, 9, 10, 15];糖果大小数组 s = [1, 3, 6, 8, 20]。
核心目标:让更多孩子得到满足,有如下规律:
1.某个糖果如果不能满足某个孩子,则该糖果也一定不能满足需求因子更大的孩子。 如,
糖果1(s = 1)不能满足孩子1(g = 2),则不能满足孩子2、孩子3、...、孩子7;
糖果2(s = 3)不能满足孩子2(g = 5),则不能满足孩子3、孩子4、...、孩子7;

2.某个孩子可以用更小的糖果满足,则没必要用更大糖果满足,因为可以保留更大的糖果
满足需求因子更大的孩子。(贪心!) 如,
孩子1(g = 2),可以被糖果2(s = 3)满足,则没必要用糖果3、糖果4、糖果5满足; 孩子2(g = 5),可以被糖果3(s = 6)满足,则没必要用糖果4、糖果5满足;

3.孩子的需求因子更小则其更容易被满足,故优先从需求因子小的孩子尝试,可以得到正 确的结果。

算法思路

1.对需求因子数组g与糖果大小数组s进行从小到大的排序。
2.按照从小到大的顺序使用各糖果尝试是否可满足某个孩子,每个糖果只尝试1次;若尝试成功,则换下一个孩子尝试;直到发现没更多的孩子或者没更多的 糖果,循环结束。



#include<vector>
#include<algorithm>
class Solution{
public:
    int findContentChildren(std::vector<int>& g,std::vector<int> & s){
        std::sort(g.begin() , g.end());
        std::sort(s.begin(), s.end());//对孩子的需求因子g与糖果大小s俩组数组排序
        int child = 0;
        int cookie = 0;//child代表满足了几个孩子,cookie代表尝试了几个糖果
        while(cookie<=s.size() && child< g.size()){
            if(g[child] <= s[cookie]){
                child ++;
            }
            cook ++ ;// 无论成功与否,每个糖果只尝试一次,cookie向后一动
        }
    }
};
测试与leetcode提交
int main(){
    Solution solve;
    std::vector<int> s;
    std::vector<int> g;
    g.push_back(5);
    g.push_back(10);
    g.push_back(2);
    g.push_back(9);
    g.push_back(15);
    g.push_back(9);
    s.push_back(6);
    s.push_back(1);
    s.push_back(20);
    s.push_back(3);
    s.push_back(8);
    printf("%d\n",solve.findContenChildren)
}

摇摆序列

一个整数序列,如果两个相邻元素的差恰好正负(负正)交替出现,则该序列被称为摇摆序列。一个小于2个元素的序列直接为摇摆序列。
例如:
序列 [1, 7, 4, 9, 2, 5],相邻元素的差 (6, -3, 5, -7, 3),该序列为摇摆序列。 序列 [1,4,7,2,5] (3, 3, -5, 3)、 [1,7,4,5,5] (6, -3, 1, 0)不是摇摆序列。
给一个随机序列,求这个序列满足摇摆序列定义的最长子序列的长度。
例如: 输入[1,7,4,9,2,5],结果为6;输入[1,17,5,10,13,15,10,5,16,8],结果为7([1,17,10,13,10,16,8] );输入[1,2,3,4,5,6,7,8,9],结果为2。
LeetCode 376. Wiggle Subsequence

[1, 17, 5, 10, 13, 15, 10, 5, 16, 8],整体不是摇摆序列: 观察该序列前6位:[1, 17, 5, 10, 13, 15...] ; 橙色部分为上升段:
其中它有3个子序列是摇摆序列: [1, 17, 5, 10, ...]
[1, 17, 5, 13, ...]
[1, 17, 5, 15, ...]

贪心规律

当序列有一段连续的递增(或递减)时,为形成摇摆子序列,我们只需要 保留这段连续的递增(或递减)的首尾元素,这样更可能使得尾部的后一个元素成为摇摆子序列的下一个元素。


算法设计

设置最长摇摆子序列长度max_length,从头至尾扫描原始序列。这个过程中 设置三种状态,即起始、上升、下降;不同的状态中,根据当前数字与前一个数字 的比较结果进行累加max_length计算或者状态切换。

#include<vector>
class Solution{
public:
    int  wiggleMaxLength(std::vector<int> & nums){
    if(nums.size() < 2){
        return num.size();//序列个数小于2时直接为摇摆序列
    }
    static const int BEGIN = 0;    
    static const int UP = 1;
    static const int DOWN = 2;//扫描序列时的三种状态
    int STATE = BEGIN;
    int max_length = 1;//摇摆序列最大长度至少为1;
    for(int i =1; 1<num.size();i++){
        switch(STATE){
        case BEGIN:
            if(nums[i]>nums[i-1]){
                STATE = UP;
                max_length++;
            }
            else if(nums[i] < nums[i-1]){
                STATE = DOWN;
                max_length++
            }
            break;
          case UP:
              if(nums[i]>nums[i-1]){
                  STATE = DOWN;
                  max_length++;
              }
              break;
          case DOWN:
              if(nums[i] < nums[i-1]){
                  STATE = UP;
                  max_length++;
              }
              break;

        }
    }
    return max_length;
}
};

相关文章

  • 第14课:关于解脱道实践原理的对话

    关于解脱道实践原理的对话 主讲:JK 妙花:能否再请赐教,贪嗔是如何形成? JK:贪嗔,是精神心法,叫作“心所法”...

  • 骗子喜欢贪子

    骗子非常喜欢爱贪的人,爱贪的人没有不被骗的,这是一对幽灵终生陪伴你我,所以股市的心法就是认清两个字,一个是“骗”,...

  • 贪贪贪,没贪到便宜

    贪贪贪,没贪到便宜 丁宏玉 昨日买点衣服,虽说提前说好了价格,但是结账时人家又给让低了100元。我就觉得赚了100...

  • 写作变现第一心法:相信和戒贪

    许多刚开始写作的朋友,或者写作有一些年头的朋友,都比较关注写作变现的这个事情。 有写作变现的念头,这是好事情,说明...

  • 小狗贪贪

    我有一只小狗,名叫贪贪。他叫贪贪的原因是这样的。 他非常贪吃。有一个月黑风高的夜晚,我门一家在共进...

  • 1128 137心法

    字数:870 在网上学到了一个刷新自己认知的“心法”,叫“137心法”。 什么是“137心法?” “137心法”就...

  • 根除贪嗔痴

    贪:贪的概念很广,修行人容易贪上“不贪”的贪,贪清净无为、贪清心寡欲、贪我是他非……其实贪的内容是无法言尽的,修的...

  • 有所贪

    这是冯唐《成事心法》一书中的一个说法。我觉得很有启发,拿出来写点感想。 冯唐认为“有所贪”是一个相对高阶一点的平衡...

  • 贪吗?不贪。只能“贪”,必须“贪”,不“贪”不行。 “贪”,最神奇的字,囊括了所有人的目标。 一...

  • 假日说剧 l 《无心法师2》奇幻不够,言情不满

    片名:无心法师2 (2017)又名: 无心法师Ⅱ / 无心法师 第二季 / Wuxin: The Monster ...

网友评论

    本文标题:贪心法

    本文链接:https://www.haomeiwen.com/subject/dboyfftx.html