目录
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] 和 [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; //题目求的是剔除的区间数,减法即可
}
}