12, 438. 找到字符串中所有字母异位词
https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/
思路1: 暴力法
思路2: 滑动窗口法
package com.shangguigu.dachang.algrithm.A04_SlidingWindow;
import java.util.ArrayList;
import java.util.List;
/**
* @author : 不二
* @date : 2022/4/10-下午8:09
* @desc : 438. 找到字符串中所有字母异位词
* https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/
**/
public class A44_findAnagrams {
public static void main(String[] args) {
// String s = "cbaebabacd", p = "abc";
// String s = "abab", p = "ab";
String s = "cbaebabacd", p = "abc";
// List<Integer> anagrams = findAnagrams_by_violance(s, p);
List<Integer> anagrams = findAnagrams_by_window(s, p);
// List<Integer> anagrams = findAnagrams(s, p);
System.out.println("结果是:" + anagrams);
}
/**
* 思路2:思路1其实就是滑动窗口的实现
* 双指针
*/
public static List<Integer> findAnagrams_by_window(String s, String p){
List<Integer> result = new ArrayList<>();
if (p.length() > s.length()) {
return result;
}
int[] target = new int[26];
for (int i = 0; i < p.length(); i++) {
target[p.charAt(i) - 'a']++;
}
int[] subStr = new int[26];
int start = 0, end = 0;
while (end < s.length()) {
char newChar = s.charAt(end);
subStr[newChar - 'a']++;
// 说明新进入的字符要么不在target中,要不字母的个数超了
// 通过移动start看下是否能抵消
// 判断当前子串是否符合要求: 说明当前的这个字符不符合要求,开始位置++,看一下是否能抵消当前字母
// 如果是抵消不了的话,那么start会一直加到end后面
// 这个地方:如果比如说某个字母abce在最后,比如这里的e,那么end指向e的时候, start可以直接加到end+1位置哈
while (subStr[newChar - 'a'] > target[newChar - 'a'] && start < end+1) {
char removeChar = s.charAt(start);
subStr[removeChar-'a']--;
start++;
}
// 到这里说明:对应字母个数都不大于目标值,而且字母个数相同。那就一定是了
if (end - start == p.length()-1) {
result.add(start);
}
end++;
}
return result;
}
/**
* 思路1:暴力解法
* 第一层遍历s
* 第二层遍历对应位置开始的窗口,看下是否满足
*
* 时间复杂度:O(nk-k*k), 因为k比n要小的多,所以k*k可以忽略
*
*/
public static List<Integer> findAnagrams_by_violance(String s, String p) {
List<Integer> result = new ArrayList<>();
if (p.length() > s.length()) {
return result;
}
int[] target = new int[26];
for (int i = 0; i < p.length(); i++) {
target[p.charAt(i) - 'a']++;
}
for (int i = 0; i < s.length() - p.length() + 1; i++) {
// System.out.print("i:" + i);
int[] subStr = new int[26];
boolean isMatched = true;
for (int j = i; j < i + p.length(); j++) {
// System.out.print( s.charAt(j));
subStr[s.charAt(j) - 'a']++;
if (subStr[s.charAt(j) - 'a'] > target[s.charAt(j) - 'a']) {
isMatched = false;
break;
}
}
// System.out.println();
if (isMatched) {
result.add(i);
}
}
return result;
}
}