贪心法

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;
}
};
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容

  • 采用步步逼近的方式构造问题的解,其下一步的选择总是在当前看来收效最快和效果最明显的那个。 使用前提: 验证贪心模式...
    芥丶未央阅读 881评论 0 2
  • http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741...
    RavenX阅读 559评论 0 1
  • 硬币问题 区间问题 字典序 其他Saruman’s ArmyFence Repair我们可以通过做出局部最优选择来...
    Nathanpro阅读 353评论 0 1
  • 背包问题 有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。要求尽可能让装入背包中的物品总价值...
    HeartGo阅读 2,715评论 0 0
  • 七天的自由写作很快就过去了。既长又短。 回顾我写的几篇,更像是记流水账,没有其他小伙伴那么用心。 这也是我的现状,...
    懒小俊阅读 259评论 1 1