layout: posttitle: PHP 滑动窗口算法实现找出所有字母异位词
subtitle: PHP 滑动窗口算法实现找出所有字母异位词
date: 2020-06-02
author: he xiaodong
header-img: img/default-post-bg.jpg
catalog: true
tags:
- Go
- PHP
- LeetCode
- 字母异位词
- 滑动窗口算法
找到字符串中所有字母异位词
给定一个字符串 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" 的字母异位词。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string
解题思路
1、我们在字符串 S 中使用双指针中的左右指针技巧,初始化 left = right = 0,把索引左闭右开区间 [left, right) 称为一个「窗口」。
2、我们先不断地增加 right 指针扩大窗口 [left, right),直到窗口中的字符串符合要求(包含了 T 中的所有字符)。
3、此时,我们停止增加 right,记录一下 left 的值,然后转而不断增加 left 指针缩小窗口 [left, right),直到窗口中的字符串不再符合要求(不包含 T 中的所有字符了)。
4、重复第 2 和第 3 步,直到 right 到达字符串 S 的尽头。
PHP 实现
function findAnagrams($s, $p) {$need = [];$window = [];$length = strlen($p);// 测试用例里有一些奇葩的,这里加个判断if ($length > strlen($s)) {return [];}// 将寻找的字符串装入 $need 数组for ($c = 0; $c < $length; $c++) {$need[$p[$c]] = isset($need[$p[$c]]) ? $need[$p[$c]] + 1 : 1;}$left = 0;$right = 0;$valid = 0;$arr = [];while ($right < strlen($s)) {// $c 是将移入窗口的字符$c = $s[$right];// 右移窗口$right++;// 进行窗口内数据的一系列更新if (isset($need[$c])) {$window[$c] = isset($window[$c]) ? $window[$c] + 1 : 1;if ($window[$c] === $need[$c]) {$valid++;}}// 判断左侧窗口是否要收缩while ($right - $left >= $length) {// 当窗口符合条件时,把起始索引加入 resif ($valid == count($need)) {$arr[] = $left;}// d 是将移出窗口的字符$d = $s[$left];// 左移窗口$left++;// 进行窗口内数据的一系列更新if (isset($need[$d])) {if ($window[$d] === $need[$d]) {$valid--;}$window[$d]--;}}}// 返回结果集return $arr;}return findAnagrams($s = "cbaebabacd", $p = "abc"); // output: [0, 6]
参考链接:
- 滑动窗口解题框架思路,强烈推荐这个网站的作者
