From f0d6255bcd4f771f295b608872079f4f597557d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E6=A0=91=E6=A3=AE?= <14021051@buaa.edu.cn> Date: Sun, 16 Sep 2018 23:26:44 +0800 Subject: [PATCH] Create 438. Find All Anagrams in a String.md --- 438. Find All Anagrams in a String.md | 77 +++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 438. Find All Anagrams in a String.md diff --git a/438. Find All Anagrams in a String.md b/438. Find All Anagrams in a String.md new file mode 100644 index 0000000..1d17b7d --- /dev/null +++ b/438. Find All Anagrams in a String.md @@ -0,0 +1,77 @@ +# [438. Find All Anagrams in a String](https://leetcode.com/problems/find-all-anagrams-in-a-string/description/) +# 思路 +## 思路一 +用固定长度(p.size)的滑动窗口在s上滑动,每次判断是否满足题意即可。 +用一个数组p_count记录每个字符出现的次数,对p中出现的字符进行累加,对窗口中出现的字符进行累减,若这个数组的元素全为0,则满足题意。 +时间复杂度O(n), 空间复杂度O(1) +每次判断p_count是否全为0时最坏都要遍历整个数组,比较费时间。思路二将解决这个问题 +## 思路二* +和思路一类似,先用一个数组p_count记录p中各字符出现的次数。然后,初始化一个长度为0的窗口,low = high = 0。 +第一步先扩展窗口,也就是在右边界high上做文章。每次high读到s的一个字符char,当p_count[char]的值大于0时,很明显就是窗口中进入了一个p中含有的字符。 +我们可以取一个变量char_num值初始为p中所有字符的总数。每次有一个p中字符从high进入窗口就char_num-–, 每次有p的字符从窗口low出去就char_num++。 +这样,当char_num == 0的时候,表明我们的窗口中包含了p中的全部字符,得到一个结果。 +# C++ +## 思路一 +``` +class Solution { +private: + bool isOK(vectorcount){ + for(int num: count) + if(num != 0) return false; + return true; + } +public: + vector findAnagrams(string s, string p) { + vectorp_count(26, 0), res; + if(p.size() > s.size()) return res; + for(int i = 0; i < p.size(); i++){ // 处理第一个窗口 + p_count[p[i] - 'a']++; + p_count[s[i] - 'a']--; + } + + int pos = 0; + while(1){ // 窗口不断移动 + if(isOK(p_count)) res.push_back(pos); + pos++; + if(pos + p.size() > s.size()) break; + p_count[s[pos - 1] - 'a']++; + p_count[s[pos + p.size() - 1] - 'a']--; + } + return res; + } +}; +``` +## 思路二 + +``` +class Solution { +public: + vector findAnagrams(string s, string p) { + vectorp_count(26, 0), res; + int char_num = p.size(); // char_num代表在p在窗口中的字符数 + if(char_num > s.size()) return res; + + for(int i = 0; i < p.size(); i++) p_count[p[i] - 'a']++; // p_count记录p中出现的字母次数 + + int low = 0, high = 0; + // 这个for循环完全可以不加,因为后面的while循环会完成同样的工作,不过加上后由于少执行了一个if语句所以会快一些 + for(; high < p.size() - 1; high++){ // 窗口初始化成p.size-1大小(因为while里面会立马增大窗口大小) + if(p_count[s[high] - 'a'] > 0) char_num--; + p_count[s[high] - 'a']--; + } + while(high < s.size()){ + if(p_count[s[high] - 'a'] > 0) char_num--; // 窗口右界右移 + p_count[s[high] - 'a']--; + high++; + + if(char_num == 0) res.push_back(low); // char_num 等于0 代表p中字符全在窗口中 + if(high - low == p.size()){ // 窗口超过长度限制,左界右移 + if(p_count[s[low] - 'a'] >= 0) char_num++; + p_count[s[low] - 'a']++; + low++; + } + } + return res; + } +}; +```