liuxuhelloworld's notebook

题目链接

https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/

解答过程

这个题目可以从暴力解法的思路入手,即顺序遍历所有子串,判断每个子串是不是p的anagram. 第一个关键点,如何判断一个子串是不是p的anagram呢?比较直接的思路是使用两个计数数组,分别计数两个字符串中每个字母的个数,然后比较这两个数组的计数是否相等。第二个关键点,如何优化计算效率呢?题目标签滑动窗口具有一定的启发性,顺序遍历子串时后一个子串的计数可以基于前一个子串的计数而来,就像一个滑动的窗口,每次右移一位,吃进右侧字母的同时吐出左侧字母。

	public List<Integer> findAnagrams(String s, String p) {
		List<Integer> ret = new ArrayList<>();

		int plen = p.length();
		int slen = s.length();
		if (slen < plen) {
			return ret;
		}

		int[] target = new int[26];
		int[] rolling = new int[26];

		for (int i = 0; i < plen; i++) {
			target[p.charAt(i) - 'a']++;
			rolling[s.charAt(i) - 'a']++;
		}
		if (compare(target, rolling)) {
			ret.add(0);
		}

		for (int i = 1; i <= s.length() - plen; i++) {
			if (s.charAt(i-1) != s.charAt(i+plen-1)) {
				rolling[s.charAt(i-1) - 'a']--;
				rolling[s.charAt(i+plen-1) - 'a']++;
			}

			if (compare(target, rolling)) {
				ret.add(i);
			}
		}

		return ret;
	}

	private boolean compare(int[] target, int[] rolling) {
		for (int i = 0; i < 26; i++) {
			if (target[i] != rolling[i]) {
				return false;
			}
		}

		return true;
	}