438.找到字符串中所有字母异位词
给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。
字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。
说明:
- 字母异位词指字母相同,但排列不同的字符串。
- 不考虑答案输出的顺序。
示例 1:
输入:s: "cbaebabacd" p: "abc" 输出:[0, 6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。 起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。
示例 2:
输入:s: "abab" p: "ab" 输出:[0, 1, 2] 解释: 起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词。 起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词。 起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词。
class Solution {
function findAnagrams($s, $p) {
//滑动窗口
$lenp = strlen($p);
$lens = strlen($s);
//p比s长,直接返回空数组
if($lens<$lenp) return [];
//构建p的哈希表
$map = [];
for($i = 0;$i<$lenp;$i++){
$map[$p[$i]]++;
}
$result = [];//存储结果
$low = $height = 0;//定义窗口上界和下届的指针
$num = 0;//窗口长度
//滑动窗口法:从左往右滑动窗口, 遇到一个p内的字符就将$num+1
while ($height<$lens) {
if(isset($map[$s[$height]]) && $map[$s[$height]]-- >= 1)
$num++;
$height++;
//如果$num==p的长度时,则窗口满足长度要求,与要求进行判断后得出结果
if($num == $lenp)
$result[] = $low;
//一旦窗口大小等于p的长度, 需要删去左端点字符, 删去时需要考虑是否要将$num-1
if($height-$low == $lenp){
if(isset($map[$s[$low]]) && $map[$s[$low]]++ >= 0)
$num--;
$low++;
}
}
return $result;
}
}
209.长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3] 输出: 2 解释: 子数组 [4,3]是该条件下的长度最小的连续子数组。
class Solution {
function minSubArrayLen($s, $nums) {
//滑动窗口
//初始条件,如果全部相加都小于$s,直接返回0
if(array_sum($nums)<$s) return 0;
$len = count($nums);
$low = 0;$height = 0;//滑动窗口左右边界
$min = $len;//最长数组长度
$sum = 0;
//右指针要后移一位
while ($height<=$len) {
//满足条件则比较,且左边界右移
if($sum >= $s) {
$min = min($min,$height-$low);
$sum -= $nums[$low++];
}else{
//没满足条件则继续相加,右边界右移
$sum += $nums[$height];
$height++;
}
}
return $min;
}
}
76.最小覆盖子串
给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC" 输出: "BANC"
说明:
- 如果 S 中不存这样的子串,则返回空字符串
""
。- 如果 S 中存在这样的子串,我们保证它是唯一的答案。
包含关系,必须包含T的所有字母,如T=“AAA”,表示答案必须包含三个A,而不是单独一个A
滑动窗口解决,leetcode上难度为hard
class Solution {
function minWindow($s, $t) {
$lent = strlen($t);
$lens = strlen($s);
if($lens<$lent) return '';//T比S长,证明S肯定不能包含T
//构建哈希表
$hash = [];
for($i = 0;$i<$lent;$i++){
$hash[$t[$i]]++;//包含的字幕,重复字符加1
}
//双指针,滑动窗口左右界
$left = $right = 0;
//记录结果数量
$count = 0;
//记录结果字符
$res = '';
//记录结果最长长度
$max = strlen($s)+1;
while ($right < $lens) {
//右边界右移,扩充窗口
if(isset($hash[$s[$right]])){
//在S中找到T的字符
$hash[$s[$right]]--;
if($hash[$s[$right]]>=0)
//当找到T中符合条件的非重复字符,结果数量+1
$count++;
//当字符串完全包含T中的字符时,开始收缩窗口和验证结果
while ($count == $lent) {
//验证结果
if(($right-$left+1)<$max){
$max = $right-$left+1;
$res = substr($s,$left,$right-$left+1);
}
//收缩窗口,左边界右移
if(isset($hash[$s[$left]])){
$hash[$s[$left]]++;//在S中找到T的字符,哈希表加一
if($hash[$s[$left]]>0)
$count--;//当哈希表中某一值大于0时,则包含数减一
}
$left++;//左边界右移
}
}
$right++;//右边界右移
}
return $res;
}
}
LeetCode上类似滑动窗口题目还有3