·题目描述
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 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" 的异位词。
·解题思路
之前的思路都是滑动窗口循环,但是事实证明想多了只需要每次对s字符串中len(p)长度的子字符串进行计数就可以了。只是计数的时候,选择使用哈希表,下标采用编码值(但是其实采用字典应该也可以)只是时间复杂度会高
·代码
分为两个部分
1.统计第一个子字符串的字母出现次数。若是与count-p相同,则增加0
2.在字符串s中,进行移位,并且统计次数
class Solution(object):
def findAnagrams(self,s,p):
size_s ,size_p = len(s),len(p)
if size_s < size_p:
return 0
res = []
count_s = [0] * 26
count_p = [0] * 26
for i in range(size_p): #首次判断
count_s[ord(s[i]) - 97] += 1
count_p[ord(p[i]) - 97] += 1
if count_s == count_p :
res.append(0)
for j in range(size_s - size_p): #移位操作
count_s[ord(s[j]) - 97] -= 1
count_s[ord(s[j+size_p]) - 97] += 1
if count_s == count_p :
res.append(j+1)
return res
-----------------java解题----------------------------------------------------
利用java解题思路还是一样,创建一个哈希表用来存储关键字(作为字母异位词判断的依据)+ 单词列表,再将同一类单词归于同一个列表中,最后返回哈希表的值。
逐步语句解决上述问题:
1.创建哈希表
Map<String , List<String>> map = new HashMap<STring , List<String>>();
根据创建的哈希表,将每个单词变形后的形式转换为String格式作为key值,然后将key下的单词都添加到List<String>中。
在这里我们要先对单词形式作出修改,方便进行判断字母异位词。处理方法有两种,一种是对其进行排序,一种是对每个字母出现次数进行计数。
1)调用库函数对其排序。Arrays.sort() ,需要先把String转换为char[]才可以进行排序
for(String s : strs){
char[] array = s.toCharArray();
Arrays.sort(array); // 排序
String key = new String(array); //获取String 格式的key
}
2)对其进行计数
public String count(String[] strs){
int[] count = new int[26];
for(String s : strs){
int n = s.length();
for(int i = 0 ; i < n ; i ++){
int index = s.charAt(i) - 'a';
count[index] ++;
}
StringBuilder str = new StringBuilder();
for(int i = 0; i < 26; i ++){
if(count[i] != 0){
char c = (char) ('a' + i);
str.append(c);
str.append(count[i]);//输出结果为a2b1c1
}
}
String key = str.toString();
return key;
}
}
2. 将同一类的单词放入同一个列表
这时候,不管前面创建key值方式有何不同,该步骤都相同。
List<String> list = map.getOrDefault(key , new ArrayList<String>);
list.add(s);//不管是否为空,都需要把s放入list中
map.put(key , list); //实现将键值对放入哈希表中
这句话调用了封装好的函数,getOrDefault,
具体来说,getOrDefault(key, defaultValue)
方法会尝试从 Map 中获取键 key
对应的值。如果该键存在,则返回其对应的值;如果该键不存在,则返回指定的默认值 defaultValue
。
在你提供的例子中,map.getOrDefault(key, new ArrayList<String>())
表示从 Map 中获取键 key
对应的值。如果键 key
存在,则返回其对应的值;如果键 key
不存在,则返回一个新创建的空列表 new ArrayList<String>()
作为默认值。
这个方法通常用于避免在获取值时出现空指针异常。如果你尝试获取的键不存在,而你希望在这种情况下返回一个默认值(比如一个空列表),那么你可以使用 getOrDefault
方法。
3. 返回值,不需要关键字
List<List<String>> result = new ArrayList<List<string>>(map.values());
return result;