力扣-438-找到字符串中所有字母异位词
异位词就是长度和组成字符和目标字符相同的字符串
第一想法是这样的
vector<int> findAnagrams(string s, string p) { int n1 = s.size(); int n2 = p.size(); for (int i = 0; i < n1 - n2; i++) { for (int j = i; j < i + n2; j++) { // 判断接下来n2个字符是否覆盖了p中的出现的所有字符 } } }
这里是否覆盖怎么判断?用set?p中的字符可能重复吧,那就用hashset,value是字符出现的次数
每次copy一个hashset,value不为0就-1,等于0删除。结束如果hashset为空就是
但是很明显这样的时间复杂度和空间复杂度都差
而且最大长度3*104多半边界测试用例要超时,必须找到优化的方法
逐个匹配字符…
看题解是“滑动窗口”,理解一下
题解方法一的巧妙之处在于:
- 把字符比较转为了ASCII码数字
- 把逐个字符的相等比较转换为了词频数组的写相等比较
vector<int> findAnagrams(string s, string p) { int sLen = s.size(), pLen = p.size(); if (sLen < pLen) return {}; vector<int> ans, sCount(26), pCount(26); // 这里只统计了p长度的s词频 for (int i = 0; i < pLen; i++) { ++sCount[s[i] - 'a']; ++pCount[s[i] - 'a']; } // 通过直接判断数组巧妙地避免了挨个判断字符 if (sCount == pCount) ans.push_back(0); for (int i = 0; i < sLen - pLen; i++) { // 通过删除新增一个词频来实现滑动窗口 --sCount[s[i] - 'a']; ++sCount[s[i + pLen] - 'a']; if (sCount == pCount) ans.push_back(i + 1); } return ans; }
方法二则是更进一步,将逐个字符相等比较转为了所有字符的ASCII码值和相等
之所以这题能用“滑动窗口”也是基于了ASCII码
但是这里不能是简单的ASCII码加和,因为可能出现字符不一致但是ASCII码和一致的情况
本文作者:YaosGHC
本文链接:https://www.cnblogs.com/yaocy/p/16891981.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步