力扣-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多半边界测试用例要超时,必须找到优化的方法

逐个匹配字符…

看题解是“滑动窗口”,理解一下

题解方法一的巧妙之处在于:

  1. 把字符比较转为了ASCII码数字
  2. 把逐个字符的相等比较转换为了词频数组的写相等比较
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码和一致的情况

posted @ 2022-11-15 14:25  YaosGHC  阅读(44)  评论(0)    收藏  举报