leetcode hot 100
找到字符串中所有字母异位词
描述
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
解题思路
1、暴力求解:判断是否是异位词还是用排序后字符串是否相等为依据;根据P的长度为窗口在S上滑动;复杂度为O(s.length)O(p.lengthlog(p.length));
2、滑动窗口+字符数组,窗口思想一致,判定是否是异位词,这里用的是字符出现次数统计数组来判断;这里比暴力求解优化的地方就是[i+1, j+1]是在在[i, j]的基础上做判断,节约了这部分时间成本。
代码段
// Java
// 暴力求解
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res = new ArrayList<>();
int start = 0;
String target = sorted(p);
while (start + p.length() <= s.length()) {
if (target.equals(sorted(s.substring(start, start + p.length())))) {
res.add(start);
}
start++;
}
return res;
}
public String sorted(String s) {
char[] chars = s.toCharArray();
Arrays.sort(chars);
return String.valueOf(chars);
}
// 滑动 + 字符统计数组
class Solution {
public List<Integer> findAnagrams(String s, String p) {
int n = s.length(), m = p.length();
List<Integer> res = new ArrayList<>();
if(n < m) return res;
int[] pCnt = new int[26];
int[] sCnt = new int[26];
for(int i = 0; i < m; i++){
pCnt[p.charAt(i) - 'a']++;
sCnt[s.charAt(i) - 'a']++;
}
if(Arrays.equals(sCnt, pCnt)){
res.add(0);
}
for(int i = m; i < n; i++){
sCnt[s.charAt(i - m) - 'a']--;
sCnt[s.charAt(i) - 'a']++;
if(Arrays.equals(sCnt, pCnt)){
res.add(i - m + 1);
}
}
return res;
}
}
// Kotlin
// Python
// Go
// JavaScript
// C++
// Rust
技巧总结
滑动窗口可将复杂度降至O(n),异位词可用字符统计数组进行比较