【PHP解法==LeetCode(贪心算法)】455.分发饼干 && 392.判断子序列 && 435.无重叠区间

目录

455.分发饼干

392.判断子序列

435.无重叠区间


455.分发饼干

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

注意:

你可以假设胃口值为正。
一个小朋友最多只能拥有一块饼干。

示例 1:

输入: [1,2,3], [1,1]
输出: 1
解释: 
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。

示例 2:

输入: [1,2], [1,2,3]
输出: 2
解释: 
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.

解法:(1)尝试将最大的饼干给最贪心的小朋友,把大小为3的饼干给贪心指数为2的小朋友

(2)如果最大的饼干可以满足最贪心的小朋友,这样留给次贪心的小朋友的饼干也将是当前最大的饼干,将大小为2 的饼干给贪心指数为1的小朋友

(3)如果无法满足,则说明所有的饼干都肯定无法满足最贪心的小朋友,此时只能将这块最大的饼干去尝试满足次贪心的小朋友

(4)以此类推

 

class Solution {
    /**
     * @param Integer[] $g
     * @param Integer[] $s
     * @return Integer
     */
    function findContentChildren($g, $s) {
        rsort($g);rsort($s);        //从大到小排序
        $leng = count($g);          //计算小朋友的数量
        $lens = count($s);          //计算饼干的数量
        $indexg = $indexs = 0;      //计算当前的饼干下标和小朋友下标
        $res = 0;                   //保存最终结果
        while ($indexg<$leng && $indexs<$lens) {    //遍历数组,只要不越界就行
            if($s[$indexs] >= $g[$indexg]){         //如果当前的饼干满足当前的小朋友
                $res++;                             //则记录结果+1
                $indexg++;                          //下标都往下一位
                $indexs++;
            }else{
                $indexg++;                          //否则尝试满足下一个次贪心的小朋友
            }
        }
        return $res;
    }
}

392.判断子序列

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace""abcde"的一个子序列,而"aec"不是)。

示例 1:
s = "abc"t = "ahbgdc"   返回 true.

示例 2:
s = "axc"t = "ahbgdc"   返回 false.

该题简单粗暴直接,只需要按顺序找到s字符串在t中的位置即可

class Solution {
    /**
     * @param String $s
     * @param String $t
     * @return Boolean
     */
    function isSubsequence($s, $t) {
        $lens = strlen($s);         //取s的长度
        $index = 0;                 //定义当前找到的下标
        for($i=0;$i<$lens;$i++){    //遍历s
            $pos = strpos($t,$s[$i],$index);    //寻找当前s中的字母在t的index下标往后能否找到
            if($pos === false){                 //找不到直接返回false
                return false;
            }else{
                $index = $pos+1;                //找到则重新定义index下标
            }
        }
        return true;
    }
}

435.无重叠区间

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

注意:

  1. 可以认为区间的终点总是大于它的起点。
  2. 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。

示例 1:

输入: [ [1,2], [2,3], [3,4], [1,3] ]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。

示例 2:

输入: [ [1,2], [1,2], [1,2] ]
输出: 2
解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。

示例 3:

输入: [ [1,2], [2,3] ]
输出: 0
解释: 你不需要移除任何区间,因为它们已经是无重叠的了。

分析:可以把问题转变成 给定一个区间的集合,问最多保留多少个区间,使剩余区间互不重叠。

暴力解法:找出所有子区间的组合,之后判断它不重叠,O((2^n)*n),2^n:找出所有子序列,*n:判断是否重叠

对于这种区间排序来说,一般利用起始点/终止点进行排序

解法:(1)动态规划:对于组合来说,可以思考是否可以用动态规划解题,该题类似于最长上升子序列,如下博文解析,对于该题则求出可以保留的最长的不重叠子区间,再去做减法即可

【PHP解法==LeetCode(动态规划4-(最长子序列))】300.最长上升子序列 && 376.摆动序列 && 5.最长回文子串 && 516.最长回文子序列 && 最长公共子序列/串

(2)贪心算法:每次选择中,每个区间的结尾很重要,结尾越小,留给后面越大的空间,后面越有可能容纳更多区间。按照区间的结尾排序,每次选择结尾最早的且和前一个区间不重叠的区间

/**
 * Definition for an interval.
 * class Interval {
 *     public $start = 0;
 *     public $end = 0;
 *     function __construct(int $start = 0, int $end = 0) {
 *         $this->start = $start;
 *         $this->end = $end;
 *     }
 * }
 */
/**************  动态规划:6536ms  **************/
class Solution {
    /**
     * @param Interval[] $intervals
     * @return Integer
     */
    function eraseOverlapIntervals($intervals) {
        $len = count($intervals);               //计算区间总数
        if($len == 0) return 0;                 //初始化判断区间是否为空
        usort($intervals, function($i,$j){      //对区间进行排序,以起始点进行排序
            if($i->start == $j->start){         //起始点相同则,终止点小的靠前
                return $i->end > $j->end;
            }
            return $i->start > $j->start;       //否则起始点小的靠前
        }); 
        $dp = [];                               //初始化动态规划数组
        for($i=0;$i<$len;++$i){
            $dp[$i] = 1;                        //初始化单个区间是不重叠的区间,为 1
            for($j=0;$j<$i;$j++){               //判断其之前的区间是否可以与该区间构成不重叠的区间
                if($intervals[$i]->start >= $intervals[$j]->end){   //该区间的起始点大于前面区间的结束点
                    $dp[$i] = max($dp[$i],1+$dp[$j]);               //则找到不重叠的区间,区间数+1
                }
            }
        }
        $res = 0;                               //遍历动态规划数组,找出保留的最长不重叠区间
        for($i=0;$i<$len;++$i){
            $res = max($res,$dp[$i]);
        }
        return $len - $res;                     //题目求的是剔除的区间数,减法即可
    }
}
/**************  贪心算法:60ms  **************/
class Solution {
    /**
     * @param Interval[] $intervals
     * @return Integer
     */
    function eraseOverlapIntervals($intervals) {
        $len = count($intervals);               //计算区间总数
        if($len == 0) return 0;                 //初始化判断区间是否为空
        usort($intervals, function($i,$j){      //对区间进行排序,以终止点进行排序
            if($i->end == $j->end){             //终止点相同则,起始点小的靠前
                return $i->start > $j->start;
            }
            return $i->end > $j->end;           //否则终止点小的靠前
        });
        $res = 1;                               //初始化最终结果
        $pre = 0;                               //记录前一个区间的下标
        for($i=1;$i<$len;++$i){                 //遍历整个数组
            //如果当前的区间起始小于前一个区间的结尾
            if($intervals[$i]->start >= $intervals[$pre]->end){   
                $res++;                         //找到一个新的不重叠区间
                $pre = $i;                      //标记该点的为新的前一个下标点,因为该点的结尾已经排序为最小的终止点
            }
        }
        return $len - $res;                     //题目求的是剔除的区间数,减法即可
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值