滑动窗口、哈希表
滑动窗口模板
问题类型 | 典型题干关键词 | 固定长度? | 例题 |
1. 最长/最短子数组满足某条件 | “最长”“最短”“连续” | 可变 | 最长无重复子串、最短覆盖子串 |
2. 固定长度子数组统计 | “长度为 k 的连续” | 固定 | 长度为 k 的最大平均值、固定大小子数组的最大和 |
3. 计数/是否存在满足条件的子数组 | “是否存在”“共有多少个” | 均可 | 和等于目标值的子数组个数 |
4. 两个子数组/字符串比较 | “两个”“相等” | 均可 | 找到字符串中所有字母异位词 |
模板:求满足条件的最短/最长/计数子数组(子串)
数组正数、负数、零都通用,按需改 while 条件即可
public int slideWindow(int[] nums, int k) {int left = 0, ans = 0; // 1. 答案变量按需改int sum = 0; // 2. 维护窗口指标(和、计数、哈希表…)for (int right = 0; right < nums.length; right++) {sum += nums[right]; // 3. 右边界右移,扩大窗口while (left <= right && 满足收缩条件) { // 4. 需要收缩就循环更新答案; // 5. 在收缩前更新(最短/计数等)sum -= nums[left]; // 6. 去掉头元素left++; // 7. 左边界右移(窗口缩小)}更新答案; // 8. 也可以在扩张后更新(最长/计数等)}return ans;
}
哈希表
使用场景:
快速查找:当需要快速判断某个元素是否存在于集合中时,哈希表可以提供平均 O(1) 时间复杂度的查找操作。
数据去重:可以利用哈希表快速检测重复元素,确保数据的唯一性。
缓存实现:哈希表可以用于实现缓存系统,通过键值对的形式存储数据,提高数据的访问速度。
数据索引:哈希表可以用于构建数据的索引,加快数据的检索速度。
import java.util.HashSet;
import java.util.Set;public class TwoSum {判断数组中是否存在两个元素,使得它们的和等于 target@param nums 输入数组@param target 目标和@return true 表示存在这样两个元素,false 表示不存在public static boolean hasTwoSum(int[] nums, int target) {//创建一个哈希集合,用来存放“已经遍历过的数字”HashSet 基于哈希表实现Set<Integer> seen = new HashSet<>();// 2. 从头到尾扫描数组for (int num : nums) {// 3. 计算当前数字 num 所需要的“另一半”int complement = target - num;// 4. 在常数时间内查哈希表:另一半是否出现过?if (seen.contains(complement)) {// 5. 出现过,说明 num + complement == target,任务完成return true;}// 6. 否则把当前数字加入哈希表,供后面的数字使用seen.add(num);}// 7. 扫完整个数组都没找到,返回 falsereturn false;}// 简单测试public static void main(String[] args) {int[] nums = {2, 7, 11, 15};int target = 9;System.out.println(hasTwoSum(nums, target)); // 输出 true,因为 2+7==9}
}
判断字母出现的次数
String s = "HelloWorld".toLowerCase();
int[] freq = new int[26]; // 0 对应 'a',25 对应 'z'
for (char c : s.toCharArray()) {if (c >= 'a' && c <= 'z') { // 过滤非字母freq[c - 'a']++;}
}
// 打印示例
for (int i = 0; i < 26; i++) {if (freq[i] > 0)System.out.println((char) (i + 'a') + " : " + freq[i]);
}
判断两字符串每个字母出现次数是否相同
public static boolean sameLetterCount(String s1, String s2) {int[] cnt1 = countLetters(s1);int[] cnt2 = countLetters(s2);return Arrays.equals(cnt1, cnt2); // Java 内置数组比较
}private static int[] countLetters(String s) {int[] freq = new int[26];for (char c : s.toLowerCase().toCharArray()) {if (c >= 'a' && c <= 'z') { // 忽略非字母freq[c - 'a']++;}}return freq;
}
重复元素HashSet<Integer> set = new HashSet<>()
HashSet<Integer> set = new HashSet<>(); 这段代码创建了一个用于存储整数的集合,这个集合会自动去除重复的元素。它主要用在以下几种常见的场景:
1. 需要去除重复元素时 当你从某个数据源(如数组、列表等)读取数据,但不希望其中有重复的元素时,可以使用 HashSet set.add(number);
2. 需要快速判断某个元素是否已存在时 set.add(i);
3. 实现一些算法问题时 例如在“快乐数”问题中,用来记录已经计算过的数字,以检测是否存在循环: set.add(n);
4. 实现简单的缓存功能时:当你需要一个简单的缓存来存储最近访问过的元素,并且希望快速判断某个元素是否已经在缓存中时:set.add(someValue);判断元素是否在缓存中
5. 实现集合运算时 set1.retainAll(set2);
6.!set.add(nums[i]) 如果nums[i]已经在集合中,则返回 true,表示数组中存在重复元素。